Swift 項(xiàng)目總結(jié) 06 - 基于控制器的全局狀態(tài)欄管理

發(fā)現(xiàn)問題

全局管理和局部管理狀態(tài)欄

iOS 7 以前,我們只有基于 UIApplication 單例類的全局狀態(tài)欄管理:

extension UIApplication {
    // Setting the statusBarStyle does nothing if your application is using the default UIViewController-based status bar system.
    @available(iOS, introduced: 2.0, deprecated: 9.0, message: "Use -[UIViewController preferredStatusBarStyle]")
    open func setStatusBarStyle(_ statusBarStyle: UIStatusBarStyle, animated: Bool)
    
    // Setting statusBarHidden does nothing if your application is using the default UIViewController-based status bar system.
    @available(iOS, introduced: 3.2, deprecated: 9.0, message: "Use -[UIViewController prefersStatusBarHidden]")
    open func setStatusBarHidden(_ hidden: Bool, with animation: UIStatusBarAnimation)
}

我們使用起來大概這樣:

// 設(shè)置狀態(tài)欄樣式
UIApplication.shared.statusBarStyle = .default
// 設(shè)置狀態(tài)欄是否隱藏
UIApplication.shared.isStatusBarHidden = false
// 設(shè)置狀態(tài)欄是否隱藏店茶,變化過程是否需要?jiǎng)赢?UIApplication.shared.setStatusBarHidden(false, with: .fade)

但在 iOS 7 以后蛹找,蘋果推出了另外一套狀態(tài)欄管理機(jī)制姨伤,即基于控制器的局部狀態(tài)欄管理,從官方注釋可以看出這種機(jī)制是蘋果推薦使用的:

extension UIViewController {
    @available(iOS 7.0, *)
    open var preferredStatusBarStyle: UIStatusBarStyle { get } // Defaults to UIStatusBarStyleDefault

    @available(iOS 7.0, *)
    open var prefersStatusBarHidden: Bool { get } // Defaults to NO

    // Override to return the type of animation that should be used for status bar changes for this view controller. This currently only affects changes to prefersStatusBarHidden.
    @available(iOS 7.0, *)
    open var preferredStatusBarUpdateAnimation: UIStatusBarAnimation { get } // Defaults to UIStatusBarAnimationFade

    // 手動(dòng)觸發(fā)狀態(tài)欄狀態(tài)更新
    @available(iOS 7.0, *)
    open func setNeedsStatusBarAppearanceUpdate()
}

我們使用起來大概這樣:

class ViewController: UIViewController {
    // 狀態(tài)欄是否隱藏
    override var prefersStatusBarHidden: Bool {
        return false
    }
    // 狀態(tài)欄樣式
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .default
    }
    // 狀態(tài)欄隱藏動(dòng)畫
    override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
        return .fade
    }
}

默認(rèn)情況下熄赡,狀態(tài)欄都是基于控制器的狀態(tài)管理姜挺,這 2 種狀態(tài)欄管理機(jī)制可以通過在 info.plist 修改配置進(jìn)行選擇

基于控制器的全局管理單例類

2 種管理狀態(tài)欄的形式各有優(yōu)缺點(diǎn):

全局管理

  • 優(yōu)點(diǎn):管理方便,代碼簡(jiǎn)潔
  • 缺點(diǎn):狀態(tài)是全局共享的彼硫,相互影響

局部管理

  • 優(yōu)點(diǎn):狀態(tài)是分離到各個(gè)控制器炊豪,互不影響
  • 缺點(diǎn):管理不方便凌箕,管理代碼分散到各個(gè)控制器

我想結(jié)合了這 2 種管理機(jī)制的優(yōu)點(diǎn),開發(fā)一個(gè)基于控制器的全局管理單例類 StatusBarManager词渤,即能像 UIApplication 那樣簡(jiǎn)潔的管理狀態(tài)欄牵舱,又能像 UIViewController 那樣分離的管理狀態(tài)欄。

分析問題

基于控制器的全局管理實(shí)現(xiàn)

首先我們就需要先把基于控制器的管理狀態(tài)欄轉(zhuǎn)變成單例類管理狀態(tài)欄缺虐,這很簡(jiǎn)單芜壁,類似下面這樣實(shí)現(xiàn),具體內(nèi)部實(shí)現(xiàn)下面會(huì)給出源碼:

/// 自定義基類控制器高氮,重載 prefersStatusBarHidden 等方法
class BasicViewController: UIViewController {
    
    override var prefersStatusBarHidden: Bool {
        return StatusBarManager.shared.isHidden
    }
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return StatusBarManager.shared.style
    }
    override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
        return StatusBarManager.shared.animation
    }
}

分離的狀態(tài)欄狀態(tài)實(shí)現(xiàn)

實(shí)現(xiàn)分離的狀態(tài)管理才是我們的重點(diǎn)慧妄,不然我們直接使用全局管理就行了,沒必要這么麻煩剪芍,首先我們要理解什么是分離的狀態(tài)管理塞淹,先看下圖:

當(dāng)我們顯示前面視圖時(shí),后面視圖的狀態(tài)欄變化是不會(huì)影響到前面視圖的狀態(tài)欄狀態(tài)罪裹,這就是狀態(tài)欄狀態(tài)的分離饱普。

要實(shí)現(xiàn)這個(gè)功能,我聯(lián)系到控制器導(dǎo)航使用的是 push 和 pop 操作状共,present 和 dismiss 操作也可以看成一個(gè) push 和 pop 操作套耕,我就想那我的狀態(tài)欄狀態(tài)是否也能通過 push 和 pop 進(jìn)行管理呢?

看起來是可以峡继,但我們要想到另外一個(gè)問題冯袍,那就是分頁控制器用 push 和 pop 管理狀態(tài)欄狀態(tài)是不行的,因?yàn)槭峭瑢蛹?jí)控制器鬓椭,那就需要有多分支的存儲(chǔ)結(jié)構(gòu)颠猴,不能用線性表結(jié)構(gòu),我想到了數(shù)據(jù)結(jié)構(gòu)里的樹結(jié)構(gòu)小染!再仔細(xì)一想翘瓮,UIView 視圖層次不就是一個(gè)樹結(jié)構(gòu)嗎?好裤翩,就決定是你了W手选!踊赠!

解決問題

樹結(jié)構(gòu)示意圖:

import UIKit

/// 狀態(tài)欄單一狀態(tài)節(jié)點(diǎn)
class StatusBarState: NSObject {
    static let defaultKey: String = "StatusBarState.default.root.key"
    
    var isHidden: Bool = false
    var style: UIStatusBarStyle = .lightContent
    var animation: UIStatusBarAnimation = .fade
    var key: String = defaultKey
    // 子節(jié)點(diǎn)數(shù)組
    var subStates: [StatusBarState] = []
    // 父節(jié)點(diǎn)呵扛,為 nil 說明是根節(jié)點(diǎn)
    weak var superState: StatusBarState?
    // 下一個(gè)路徑節(jié)點(diǎn),為 nil 說明是葉子節(jié)點(diǎn)
    weak var nextState: StatusBarState?
    
    override var description: String {
        return "{ key=\(self.key) selected=\(String(describing: self.nextState?.key)) }"
    }
}

/// 全局狀態(tài)欄狀態(tài)管理單例類
class StatusBarManager {
    static let shared = StatusBarManager()
    // MARK: - 屬性
    /// 狀態(tài)鍵集合筐带,用來判斷樹中是否有某個(gè)狀態(tài)
    fileprivate var stateKeys: Set<String> = Set<String>()
    /// 根節(jié)點(diǎn)狀態(tài)今穿,從這個(gè)根節(jié)點(diǎn)可以遍歷到整個(gè)狀態(tài)樹
    fileprivate var rootState: StatusBarState!
    /// 更新狀態(tài)欄動(dòng)畫時(shí)間
    fileprivate var duration: TimeInterval = 0.1
    /// 當(dāng)前狀態(tài)
    fileprivate var currentState: StatusBarState!
    
    /// 以下3個(gè)計(jì)算屬性都是取當(dāng)前狀態(tài)顯示以及更新當(dāng)前狀態(tài)
    var isHidden: Bool {
        get {
            return currentState.isHidden
        }
        set {
            setState(for: currentState.key, isHidden: newValue)
        }
    }
    var style: UIStatusBarStyle {
        get {
            return currentState.style
        }
        set {
            setState(for: currentState.key, style: newValue)
        }
    }
    var animation: UIStatusBarAnimation {
        get {
            return currentState.animation
        }
        set {
            setState(for: currentState.key, animation: newValue)
        }
    }
    
    // MARK: - 方法
    /// 初始化根節(jié)點(diǎn)
    fileprivate init() {
        rootState = StatusBarState()
        currentState = rootState
        stateKeys.insert(rootState.key)
    }
    
    /// 為某個(gè)狀態(tài)(root)添加子狀態(tài)(key),當(dāng) root = nil 時(shí)伦籍,表示添加到根狀態(tài)上
    @discardableResult
    func addSubState(with key: String, root: String? = nil) -> StatusBarState? {
        guard !stateKeys.contains(key) else { return nil }
        stateKeys.insert(key)
        
        let newState = StatusBarState()
        newState.key = key
        
        // 找到鍵為 root 的父狀態(tài)
        var superState: StatusBarState! = rootState
        if let root = root {
            superState = findState(root)
        }
        newState.isHidden = superState.isHidden
        newState.style = superState.style
        newState.animation = superState.animation
        newState.superState = superState
        
        // 添加進(jìn)父狀態(tài)的子狀態(tài)集合中蓝晒,默認(rèn)選中第一個(gè)
        superState.subStates.append(newState)
        if superState.nextState == nil {
            superState.nextState = newState
        }
        
        // 判斷是否在當(dāng)前狀態(tài)上添加子狀態(tài)腮出,是的話,自動(dòng)切換當(dāng)前狀態(tài)
        if currentState.key == superState.key {
            currentState = newState
            updateStatusBar()
        }
        
        printAllStates()
        return newState
    }
    
    /// 刪除某個(gè)狀態(tài)及其子狀態(tài)樹
    func removeState(with key: String) {
        guard stateKeys.contains(key) else { return }
        let state = findState(key)
        let isContainCurrentState = findStateInTree(state, key: currentState.key) != nil
        if state.subStates.count > 0 {
            removeSubStatesInTree(state)
        }
        // 是否有父狀態(tài)芝薇,如果沒有胚嘲,說明要?jiǎng)h除的是根狀態(tài),根節(jié)點(diǎn)是不能刪除的洛二,否則刪除該節(jié)點(diǎn)并切換當(dāng)前狀態(tài)
        if let superState = state.superState {
            stateKeys.remove(state.key)
            if let index = superState.subStates.index(of: state) {
                superState.subStates.remove(at: index)
            }
            superState.nextState = superState.subStates.first
            if isContainCurrentState {
                if let selectedState = superState.nextState {
                    currentState = selectedState
                } else {
                    currentState = superState
                }
                updateStatusBar()
            }
            
        }
        printAllStates()
    }
    
    /// 更改某個(gè)狀態(tài)(root)下要顯示直接的子狀態(tài)節(jié)點(diǎn)(key)
    func showState(for key: String, root: String? = nil) {
        guard stateKeys.contains(key) else { return }
        
        // 改變父狀態(tài) nextState 屬性
        let rootState = findState(root)
        for subState in rootState.subStates {
            if subState.key == key {
                rootState.nextState = subState
                break
            }
        }
        // 找到切換后的當(dāng)前狀態(tài)
        let newCurrentState = findCurrentStateInTree(rootState)
        if newCurrentState != currentState {
            currentState = newCurrentState
            updateStatusBar()
        }
        printAllStates()
    }
    
    /// 刪除某個(gè)狀態(tài)下的子狀態(tài)樹
    func clearSubStates(with key: String, isUpdate: Bool = true) {
        guard stateKeys.contains(key) else { return }
        let state = findState(key)
        var needUpdate: Bool = false
        if findStateInTree(state, key: currentState.key) != nil {
            currentState = state
            needUpdate = true
        }
        if state.subStates.count > 0 {
            removeSubStatesInTree(state)
        }
        if needUpdate && isUpdate {
            updateStatusBar()
        }
        printAllStates()
    }
    
    /// 負(fù)責(zé)打印狀態(tài)樹結(jié)構(gòu)
    func printAllStates(_ method: String = #function) {
        debugPrint("\(method): currentState = \(currentState.key)")
        printAllStatesInTree(rootState, deep: 0, method: method)
    }

    /// 更新棧中 key 對(duì)應(yīng)的狀態(tài)馋劈,key == nil 表示棧頂狀態(tài)
    func setState(for key: String? = nil, isHidden: Bool? = nil, style: UIStatusBarStyle? = nil, animation: UIStatusBarAnimation? = nil) {
        var needUpdate: Bool = false
        let state = findState(key)
        if let isHidden = isHidden, state.isHidden != isHidden {
            needUpdate = true
            state.isHidden = isHidden
        }
        if let style = style, state.style != style {
            needUpdate = true
            state.style = style
        }
        if let animation = animation, state.animation != animation {
            needUpdate = true
            state.animation = animation
        }
        // key != nil 表示更新對(duì)應(yīng) key 的狀態(tài),需要判斷該狀態(tài)是否是當(dāng)前狀態(tài)
        if let key = key {
            guard let currentState = currentState, currentState.key == key else { return }
        }
        // 狀態(tài)有變化才需要更新視圖
        if needUpdate {
            updateStatusBar()
        }
    }
    
    /// 開始更新狀態(tài)欄的狀態(tài)
    fileprivate func updateStatusBar() {
        DispatchQueue.main.async { // 在主線程異步執(zhí)行 避免同時(shí)索取同一屬性
            // 如果狀態(tài)欄需要?jiǎng)赢嫞╢ade or slide)晾嘶,需要添加動(dòng)畫時(shí)間妓雾,才會(huì)有動(dòng)畫效果
            UIView.animate(withDuration: self.duration, animations: {
                UIApplication.shared.keyWindow?.rootViewController?.setNeedsStatusBarAppearanceUpdate()
            })
        }
    }
    
    /// 從狀態(tài)樹中找到對(duì)應(yīng)的節(jié)點(diǎn)狀態(tài),沒找到就返回根節(jié)點(diǎn)
    fileprivate func findState(_ key: String? = nil) -> StatusBarState {
        if let key = key { // 查找
            if let findState = findStateInTree(rootState, key: key) {
                return findState
            }
        }
        return rootState
    }
    
    /// 從狀態(tài)樹中找到對(duì)應(yīng)的節(jié)點(diǎn)狀態(tài)的遞歸方法
    fileprivate func findStateInTree(_ state: StatusBarState, key: String) -> StatusBarState? {
        if state.key == key {
            return state
        }
        for subState in state.subStates {
            if let findState = findStateInTree(subState, key: key) {
                return findState
            }
        }
        return nil
    }
    
    /// 刪除某個(gè)狀態(tài)下的所有子狀態(tài)的遞歸方法
    fileprivate func removeSubStatesInTree(_ state: StatusBarState) {
        state.subStates.forEach { (subState) in
            stateKeys.remove(subState.key)
            removeSubStatesInTree(subState)
        }
        state.subStates.removeAll()
    }
    
    /// 找到某個(gè)狀態(tài)下的最底層狀態(tài)
    fileprivate func findCurrentStateInTree(_ state: StatusBarState) -> StatusBarState? {
        if let nextState = state.nextState {
            return findCurrentStateInTree(nextState)
        }
        return state
    }
    
    /// 打印狀態(tài)樹結(jié)構(gòu)的遞歸方法
    fileprivate func printAllStatesInTree(_ state: StatusBarState, deep: Int = 0, method: String) {
        debugPrint("\(method): \(deep) - state=\(state)")
        for subState in state.subStates {
            printAllStatesInTree(subState, deep: deep + 1, method: method)
        }
    }
}

創(chuàng)建 UIViewController+StatusBar 分類和基類控制器來輔助設(shè)置垒迂,簡(jiǎn)單管理狀態(tài)欄:

/// UIViewController+StatusBar.swift
import UIKit

extension UIViewController {
    
    /// 控制器的狀態(tài)欄唯一鍵
    var statusBarKey: String {
        return "\(self)"
    }
    
    /// 設(shè)置該控制器的狀態(tài)欄狀態(tài)
    func setStatusBar(isHidden: Bool? = nil, style: UIStatusBarStyle? = nil, animation: UIStatusBarAnimation? = nil) {
        StatusBarManager.shared.setState(for: statusBarKey, isHidden: isHidden, style: style, animation: animation)
    }

    /// 添加一個(gè)子狀態(tài)
    func addSubStatusBar(for viewController: UIViewController) {
        let superKey = self.statusBarKey
        let subKey = viewController.statusBarKey
        StatusBarManager.shared.addSubState(with: subKey, root: superKey)
    }
    
    /// 批量添加子狀態(tài)君珠,樹橫向生長(zhǎng)
    func addSubStatusBars(for viewControllers: [UIViewController]) {
        viewControllers.forEach { (viewController) in
            self.addSubStatusBar(for: viewController)
        }
    }
    
    /// 從整個(gè)狀態(tài)樹上刪除當(dāng)前狀態(tài)
    func removeFromSuperStatusBar() {
        let key = self.statusBarKey
        StatusBarManager.shared.removeState(with: key)
    }
    
    /// 設(shè)置當(dāng)前狀態(tài)下的所有子狀態(tài)
    func setSubStatusBars(for viewControllers: [UIViewController]?) {
        clearSubStatusBars()
        if let viewControllers = viewControllers {
            addSubStatusBars(for: viewControllers)
        }
    }
    
    /// 通過類似壓棧的形式,壓入一組狀態(tài)娇斑,樹縱向生長(zhǎng)
    func pushStatusBars(for viewControllers: [UIViewController]) {
        var lastViewController: UIViewController? = self
        viewControllers.forEach { (viewController) in
            if let superController = lastViewController {
                superController.addSubStatusBar(for: viewController)
                lastViewController = viewController
            }
        }
    }
    
    /// 切換多個(gè)子狀態(tài)的某個(gè)子狀態(tài)
    func showStatusBar(for viewController: UIViewController?) {
        guard let viewController = viewController else { return }
        let superKey = self.statusBarKey
        let subKey = viewController.statusBarKey
        StatusBarManager.shared.showState(for: subKey, root: superKey)
    }
    
    /// 清除所有子狀態(tài)
    func clearSubStatusBars(isUpdate: Bool = true) {
        StatusBarManager.shared.clearSubStates(with: self.statusBarKey, isUpdate: isUpdate)
    }
}
/// 保證所有控制器都重載了 prefersStatusBarHidden 的方法
class BasicViewController: UIViewController {
    
    override var prefersStatusBarHidden: Bool {
        return StatusBarManager.shared.isHidden
    }
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return StatusBarManager.shared.style
    }
    override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
        return StatusBarManager.shared.animation
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    deinit {
         self.removeFromSuperStatusBar()
    }
    
    override func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
        self.addSubStatusBar(for: viewControllerToPresent)
        super.present(viewControllerToPresent, animated: flag, completion: completion)
    }
}

/// 保證所有控制器都重載了 prefersStatusBarHidden 的方法
class BasicNavigationController: UINavigationController {
    
    override var prefersStatusBarHidden: Bool {
        return StatusBarManager.shared.isHidden
    }
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return StatusBarManager.shared.style
    }
    override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
        return StatusBarManager.shared.animation
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        pushStatusBars(for: viewControllers)
    }
    
    override func setViewControllers(_ viewControllers: [UIViewController], animated: Bool) {
        clearSubStatusBars(isUpdate: false)
        pushStatusBars(for: viewControllers)
        super.setViewControllers(viewControllers, animated: animated)
    }
    
    override func pushViewController(_ viewController: UIViewController, animated: Bool) {
        topViewController?.addSubStatusBar(for: viewController)
        super.pushViewController(viewController, animated: animated)
    }
}

/// 保證所有控制器都重載了 prefersStatusBarHidden 的方法
class BasicTabBarController: UITabBarController, UITabBarControllerDelegate {
    
    override var prefersStatusBarHidden: Bool {
        return StatusBarManager.shared.isHidden
    }
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return StatusBarManager.shared.style
    }
    override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
        return StatusBarManager.shared.animation
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.setSubStatusBars(for: viewControllers)
        self.delegate = self
    }
    
    override func setViewControllers(_ viewControllers: [UIViewController]?, animated: Bool) {
        self.setSubStatusBars(for: viewControllers)
        super.setViewControllers(viewControllers, animated: animated)
    }
    
    func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
        showStatusBar(for: viewController)
    }
}

基于控制器的全局狀態(tài)欄使用:

class ViewController: BasicViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        setStatusBar(isHidden: false, style: .default)
    }
}

Demo 源碼在這里:StatusBarManagerDemo

有什么問題可以在下方評(píng)論區(qū)提出,寫得不好可以提出你的意見材部,我會(huì)合理采納的毫缆,O(∩_∩)O哈哈~,求關(guān)注求贊

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末乐导,一起剝皮案震驚了整個(gè)濱河市苦丁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌物臂,老刑警劉巖旺拉,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異棵磷,居然都是意外死亡蛾狗,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門仪媒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沉桌,“玉大人,你說我怎么就攤上這事算吩×羝荆” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵偎巢,是天一觀的道長(zhǎng)蔼夜。 經(jīng)常有香客問我,道長(zhǎng)压昼,這世上最難降的妖魔是什么求冷? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任瘤运,我火速辦了婚禮,結(jié)果婚禮上遵倦,老公的妹妹穿的比我還像新娘尽超。我一直安慰自己,他們只是感情好梧躺,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布似谁。 她就那樣靜靜地躺著,像睡著了一般掠哥。 火紅的嫁衣襯著肌膚如雪巩踏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天续搀,我揣著相機(jī)與錄音塞琼,去河邊找鬼。 笑死禁舷,一個(gè)胖子當(dāng)著我的面吹牛彪杉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播牵咙,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼派近,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了洁桌?” 一聲冷哼從身側(cè)響起渴丸,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎另凌,沒想到半個(gè)月后谱轨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吠谢,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年土童,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片囊卜。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡娜扇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出栅组,到底是詐尸還是另有隱情雀瓢,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布玉掸,位于F島的核電站刃麸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏司浪。R本人自食惡果不足惜泊业,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一把沼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吁伺,春花似錦饮睬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至窟却,卻和暖如春昼丑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背夸赫。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工菩帝, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人茬腿。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓呼奢,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親切平。 傳聞我的和親對(duì)象是個(gè)殘疾皇子控妻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件揭绑、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,102評(píng)論 4 62
  • 年少時(shí),我們總以為父母無堅(jiān)不摧郎哭,直到撞破他們的無助他匪,才明白,那是因?yàn)閻劭溲校麄儾旁敢獍缪萦⑿邸?/div>
    青梔戀閱讀 392評(píng)論 0 1
  • 今天距離開始堅(jiān)持?jǐn)z影邦蜜,已經(jīng)232天了,也是第三十三周亥至。 雖說沒有全身心地投入進(jìn)去悼沈,但是每天也都會(huì)留些時(shí)間想想拍些什...
    宮崎蟲師閱讀 241評(píng)論 2 7
  • 小胖要當(dāng)爸爸了!真替他高興姐扮。要知道絮供,為了獲得這個(gè)“職稱”的晉升,可真是不容易呢茶敏。 小胖從小就得了腎病壤靶,三十歲出頭的...
    歡樂V英雄閱讀 410評(píng)論 2 4
  • 第一次接觸韓劇是來自于很小的時(shí)候看的那部《天國(guó)的階梯》,當(dāng)年韓靜書和車誠(chéng)俊之間波折的愛情惊搏,真的是賺足了我的眼淚贮乳。那...
    陳遠(yuǎn)閱讀 392評(píng)論 1 0