Swift自動(dòng)布局SnapKit的詳細(xì)使用介紹

簡(jiǎn)介

SnapKit撬陵,一個(gè)經(jīng)典的Swift版的第三方庫(kù)江耀,專門(mén)用于項(xiàng)目的自動(dòng)布局,目前在github上的stars就高達(dá)9340顆星昂利,這是一個(gè)不小的數(shù)字,亦足以證明它存在的非凡意義和作用铁坎。作者認(rèn)為蜂奸,在iOS開(kāi)發(fā)(swift)中,它是用于項(xiàng)目最優(yōu)秀的自動(dòng)布局的必選庫(kù)之一硬萍。它的作者仍然是寫(xiě)Objective-C的第三方庫(kù)Masonry的大牛 - @Robert Payne窝撵,開(kāi)門(mén)見(jiàn)山,本文將詳細(xì)介紹介紹SnapKit的詳細(xì)使用和安裝襟铭,相信對(duì)于初入門(mén)該庫(kù)的開(kāi)發(fā)者或許會(huì)有一定的幫助碌奉,當(dāng)然,鑒于作者能力有限寒砖,如有不足之處赐劣,歡迎指點(diǎn)和批評(píng)。

Snapkit的安裝(CocoaPods)

環(huán)境配置要求:

  • iOS 8.0 / Mac OS X 10.11+
  • Xcode 8.0+
  • Swift 3.0+

安裝

在已經(jīng)安裝CocoaPods的前提下哩都, 即可以進(jìn)行下列步驟魁兼。

  • 在你的項(xiàng)目工程里的Podfile文件里面添加
source 'https://github.com/CocoaPods/Specs.git'

platform :ios, '10.0'

use_frameworks!

target '這里是你的工程名稱' do
    pod 'SnapKit', '~> 3.0'
end
  • 老生常談,運(yùn)行CocoaPods的如下命令
pod install

到此漠嵌,不出意外的話咐汞,你已經(jīng)將SnapKit集成到你的項(xiàng)目中了盖呼。然后,就開(kāi)始講怎么使用它了化撕。

Snapkit的布局使用

1几晤、 實(shí)現(xiàn)一個(gè)寬高為100,居于當(dāng)前視圖的中心的視圖布局植阴,示例代碼如下

import UIKit
import SnapKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        let testView = UIView()
        testView.backgroundColor = UIColor.cyan
        view.addSubview(testView)
        testView.snp.makeConstraints { (make) in
            make.width.equalTo(100)         // 寬為100
            make.height.equalTo(100)        // 高為100
            make.center.equalTo(view)       // 位于當(dāng)前視圖的中心
        }

    }
}

更簡(jiǎn)潔的寫(xiě)法可以

import UIKit
import SnapKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        let testView = UIView()
        testView.backgroundColor = UIColor.cyan
        view.addSubview(testView)
        testView.snp.makeConstraints { (make) in
            make.width.height.equalTo(100)    // 鏈?zhǔn)秸Z(yǔ)法直接定義寬高
            make.center.equalToSuperview()    // 直接在父視圖居中
        }

    }
}

效果圖

1.png

2蟹瘾、View2位于View1內(nèi), view2位于View1的中心掠手, 并且距離View的邊距的距離都為20

import UIKit
import SnapKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

         // 黑色視圖作為父視圖
         let view1 = UIView()
         view1.frame = CGRect(x: 0, y: 0, width: 300, height: 300)
         view1.center = view.center
         view1.backgroundColor = UIColor.black
         view.addSubview(view1)

         // 測(cè)試視圖
         let view2 = UIView()
         view2.backgroundColor = UIColor.magenta
         view1.addSubview(view2)
         view2.snp.makeConstraints { (make) in
               make.top.equalToSuperview().offset(20)      // 當(dāng)前視圖的頂部距離父視圖的頂部:20(父視圖頂部+20)
               make.left.equalToSuperview().offset(20)     // 當(dāng)前視圖的左邊距離父視圖的左邊:20(父視圖左邊+20)
              make.bottom.equalToSuperview().offset(-20)  // 當(dāng)前視圖的底部距離父視圖的底部:-20(父視圖底部-20)
              make.right.equalToSuperview().offset(-20)   // 當(dāng)前視圖的右邊距離父視圖的右邊:-20(父視圖右邊-20)
         }

    }
}

更簡(jiǎn)潔的寫(xiě)法

import UIKit
import SnapKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

         // 黑色視圖作為父視圖
         let view1 = UIView()
         view1.frame = CGRect(x: 0, y: 0, width: 300, height: 300)
         view1.center = view.center
         view1.backgroundColor = UIColor.black
         view.addSubview(view1)

         // 測(cè)試視圖
         let view2 = UIView()
         view2.backgroundColor = UIColor.magenta
         view1.addSubview(view2)
         view2.snp.makeConstraints { (make) in
            make.edges.equalToSuperview().inset(UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20))
         }

    }
}

效果圖

2.png

3憾朴、布局一個(gè)視圖view2, 讓它的水平中心線小于等于另一個(gè)視圖view2的左邊喷鸽,可以這樣布局

import UIKit
import SnapKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

         // 黑色視圖作為父視圖
         let view1 = UIView()
         view1.frame = CGRect(x: 0, y: 0, width: 300, height: 300)
         view1.center = view.center
         view1.backgroundColor = UIColor.black
         view.addSubview(view1)

         // 測(cè)試視圖
         let view2 = UIView()
         view2.backgroundColor = UIColor.magenta
         view1.addSubview(view2)
         view2.snp.makeConstraints { (make) in
            // 讓頂部距離view1的底部為10的距離
            make.top.equalTo(view1.snp.bottom).offset(10)
            // 設(shè)置寬众雷、高
            make.width.height.equalTo(100)
            // 水平中心線<=view1的左邊
            make.centerX.lessThanOrEqualTo(view1.snp.leading)
         }

    }
}

效果圖

3.png

視圖的屬性說(shuō)明

通過(guò)上面的大致簡(jiǎn)單布局我們對(duì)SnapKit有了一個(gè)基本的了解,那么做祝, 它的布局屬性是怎么來(lái)的呢砾省?和原生的布局類有什么關(guān)聯(lián)? 下面看一個(gè)SnapKit的布局屬性表

4.png

從表中剖淀,我們知道纯蛾,Snapkit的布局屬性都是源自于系統(tǒng)的NSLayoutAttribute,那么纵隔,NSLayoutAttribute是個(gè)什么呢翻诉?其實(shí),它在swift中是一個(gè)枚舉捌刮,內(nèi)部列舉了很多布局屬性諸如top碰煌、left、leading绅作、centerX等芦圾,Snapkit的布局屬性與它們都存在一一的對(duì)應(yīng)關(guān)系。

Snapkit 的 greaterThanOrEqualTo 屬性

如果想讓視圖View2的左邊>=父視圖View1的左邊俄认, 這時(shí)我們就可以用到greaterThanOrEqualTo

import UIKit
import SnapKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

         // 黑色視圖作為父視圖
         let view1 = UIView()
         view1.frame = CGRect(x: 0, y: 0, width: 300, height: 300)
         view1.center = view.center
         view1.backgroundColor = UIColor.black
         view.addSubview(view1)

         // 測(cè)試視圖
         let view2 = UIView()
         view2.backgroundColor = UIColor.magenta
         view1.addSubview(view2)
         view2.snp.makeConstraints { (make) in
            // 讓頂部距離view1的底部為10的距離
            make.top.equalTo(view1.snp.bottom).offset(10)
            // 設(shè)置寬个少、高
            make.width.height.equalTo(100)
            // 水平中心線<=view1的左邊
            make.left.greaterThanOrEqualTo(view1)

            // 或者, 和上面一行代碼一樣的效果
//            make.left.greaterThanOrEqualTo(view1.snp.left)
         }
    }
}

效果圖

5.png

其實(shí),greaterThanOrEqualTo這個(gè)屬性有點(diǎn)多余眯杏,比如上面這行代碼 make.left.greaterThanOrEqualTo(view1) 夜焦, 我們可以換成 make.left.equalToSuperview()或make.left.equalTo(view1.snp.left), 效果是一樣的岂贩,也就是說(shuō)茫经,一般情況下 >= 或 <= 我們都可以直接用equalTo來(lái)代替!

SnapKit的greaterThanOrEqualTo和lessThanOrEqualTo聯(lián)合使用

當(dāng)我們想要讓某個(gè)視圖的width或height大于等于某個(gè)特定的值,小于等于某個(gè)特定的值的時(shí)候卸伞,一般而言抹镊,Snapkit會(huì)以greaterThanOrEqualTo為準(zhǔn),這里舉一個(gè)width的例子荤傲,為了方便垮耳,這里指貼出了viewDidLoad中的代碼(其他沒(méi)必要)

 // 黑色視圖作為父視圖
 let view1 = UIView()
 view1.frame = CGRect(x: 0, y: 0, width: 300, height: 300)
 view1.center = view.center
 view1.backgroundColor = UIColor.black
 view.addSubview(view1)

 // 測(cè)試視圖
 let view2 = UIView()
 view2.backgroundColor = UIColor.magenta
 view1.addSubview(view2)
 view2.snp.makeConstraints { (make) in
    make.width.lessThanOrEqualTo(300)
    make.width.greaterThanOrEqualTo(200)
    make.height.equalTo(100)
    make.center.equalToSuperview()
 }

接著,我們來(lái)看一下效果圖

6.png

很明顯弃酌,最后的寬度是以make.width.greaterThanOrEqualTo(200)為標(biāo)準(zhǔn)的氨菇,也可以這樣的儡炼,在同時(shí)使用兩者的情況下妓湘,greaterThanOrEqualTo的優(yōu)先級(jí)略比lessThanOrEqualTo的優(yōu)先級(jí)高。值得一提的是乌询, 在上面的例子中榜贴,如果我們只設(shè)置make.width.lessThanOrEqualTo(300),那么view2是不會(huì)顯示出來(lái)的妹田,因?yàn)関iew2不知道你要表達(dá)的是要顯示多少唬党,小于等于300,到底是100還是200呢鬼佣?(這里指針對(duì)width和height)所以它不能確定這個(gè)約束的值驶拱,但是,如果我們單獨(dú)設(shè)置make.width.greaterThanOrEqualTo(200)晶衷,那么就和上面的效果一樣蓝纲,因?yàn)樗鼤?huì)以200為標(biāo)準(zhǔn)布局約束!

lessThanOrEqualTo的用于上晌纫、下税迷、左、右

如果我們想要視圖view2的左邊 <= view1.left + 10, 那么就可以直接用到lessThanOrEqualTo布局了锹漱,看下面這個(gè)例子

 // 黑色視圖作為父視圖
 let view1 = UIView()
 view1.frame = CGRect(x: 0, y: 0, width: 300, height: 300)
 view1.center = view.center
 view1.backgroundColor = UIColor.black
 view.addSubview(view1)

 // 測(cè)試視圖
 let view2 = UIView()
 view2.backgroundColor = UIColor.magenta
 view1.addSubview(view2)
 view2.snp.makeConstraints { (make) in
    make.left.lessThanOrEqualTo(20)        // <= 父視圖的左邊+20
    make.right.equalTo(-40)                // = 父視圖的右邊-40
    make.height.equalTo(100)
    make.center.equalToSuperview()
 }

效果圖

7.png

Snapkit布局的靈活性

  • Snapkit布局靈活性很強(qiáng)箭养, 我們看下面的例子, 他們的效果是一樣的
make.left.equalToSuperview().offset(10)
make.left.equalTo(10)
make.left.equalTo(view1.snp.left).offset(10)
  • 設(shè)置視圖的大小(width哥牍,height),他們效果是一樣的
make.width.height.equalTo(100)
或
make.width.equalTo(100)
make.height.equalTo(100)
或
make.size.equalTo(CGSize(width: 100, height: 100))
  • 優(yōu)先級(jí)(priority)

我們來(lái)看一下Snapkit的優(yōu)先級(jí)設(shè)置毕泌, 優(yōu)先級(jí)都是附加在約束鏈的末尾處,看下面的使用方法

// 黑色視圖作為父視圖
let view1 = UIView()
view1.frame = CGRect(x: 0, y: 0, width: 300, height: 300)
view1.center = view.center
view1.backgroundColor = UIColor.black
view.addSubview(view1)

// 測(cè)試視圖
let view2 = UIView()
view2.backgroundColor = UIColor.magenta
view1.addSubview(view2)
view2.snp.makeConstraints { (make) in
    make.width.equalTo(100).priority(666)
    make.width.equalTo(250).priority(999)
    make.height.equalTo(111)
    make.center.equalToSuperview()
}

效果圖

8.png

從上面我們可以知道, 我們?cè)O(shè)置了兩個(gè)優(yōu)先級(jí):make.width.equalTo(100).priority(666) 和 make.width.equalTo(250).priority(999)嗅辣, 那運(yùn)行結(jié)果是一個(gè)哪個(gè)為準(zhǔn)呢撼泛?顯然是以優(yōu)先級(jí)為 999的為準(zhǔn),因?yàn)?priority(999)>priotity(666)辩诞, 所以在使用Snapkit的過(guò)程中坎弯,有時(shí)我們可以使用優(yōu)先級(jí)priority來(lái)設(shè)置我們的約束, 另外,值得一提的是抠忘,SnapKit的優(yōu)先級(jí)最大值只能是 1000撩炊, 如果優(yōu)先級(jí)的數(shù)值超過(guò)1000,則運(yùn)行時(shí)就會(huì)Crash崎脉!這里要尤其注意拧咳。

  • 更新約束(引用約束)

我們可以通過(guò)保存某一個(gè)約束布局來(lái)更新相應(yīng)的約束,或者保存一組約束布局到一個(gè)數(shù)組中更新約束囚灼, 具體看下面代碼

// 保存約束(引用約束)
var updateConstraint: Constraint?

override func viewDidLoad() {
    super.viewDidLoad()

    // 黑色視圖作為父視圖
    let view1 = UIView()
    view1.frame = CGRect(x: 0, y: 0, width: 300, height: 300)
    view1.center = view.center
    view1.backgroundColor = UIColor.black
    view.addSubview(view1)

    // 測(cè)試視圖
    let view2 = UIView()
    view2.backgroundColor = UIColor.magenta
    view1.addSubview(view2)
    view2.snp.makeConstraints { (make) in
        make.width.height.equalTo(100)  // 寬高為100
        self.updateConstraint = make.top.left.equalTo(10).constraint   // 距離父視圖上骆膝、左為10
    }

    let updateButton = UIButton(type: .custom)
    updateButton.backgroundColor = UIColor.brown
    updateButton.frame = CGRect(x: 100, y: 80, width: 50, height: 30)
    updateButton.setTitle("更新", for: .normal)
    updateButton.addTarget(self, action: #selector(updateConstraintMethod), for: .touchUpInside)
    view.addSubview(updateButton)
}

// 更新約束
func updateConstraintMethod() {
    self.updateConstraint?.update(offset: 50)   // 更新距離父視圖上、左為50
}
9
  • 更新約束(snp.updateConstraints)

說(shuō)起這個(gè)updateConstraints, 我也懵逼過(guò)灶体,那么它到底有何作用呢阅签?又怎么用呢?它和一開(kāi)始就使用的makeConstraints又有什么明確的區(qū)別呢蝎抽?請(qǐng)繼續(xù)往下看

  • 說(shuō)明1:如果你這是更新某個(gè)約束或某幾個(gè)約束的常量值政钟,你就可以使用updateConstraints而不是makeConstraints

  • 說(shuō)明2:這個(gè)也是蘋(píng)果推薦用來(lái)添加或更新約束的方式

  • 說(shuō)明3:這個(gè)方法可以調(diào)用多次樟结,會(huì)相應(yīng)setNeedsUpdateConstraints, 在控制器中养交,可以寫(xiě)在override func updateViewConstraints()方法里面(當(dāng)然也可以寫(xiě)在你想要什么時(shí)候更新的點(diǎn)擊事件里面)

import UIKit
import SnapKit

class ViewController: UIViewController {

    lazy var blackView = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()

        blackView.backgroundColor = UIColor.black
        view.addSubview(blackView)
        blackView.snp.makeConstraints { (make) in

            // 四個(gè)約束確定位置和大小
            make.width.equalTo(100)
            make.height.equalTo(150)
            make.top.equalTo(10)
            make.centerX.equalToSuperview()
        }

    }

    override func updateViewConstraints() {

        blackView.snp.updateConstraints { (make) in
            // 更新距離父視圖頂部的約束(從 10 ---> 300 )
            make.top.equalTo(300)
        }

        // 根據(jù)蘋(píng)果,調(diào)用父類應(yīng)該放在末尾
        super.updateViewConstraints()
    }
}

注意:從上面的代碼中我們很明確地知道瓢宦, blackView通過(guò)width碎连、height、top驮履、centerX確定了它本身的大小和位置鱼辙, 但是, 在run出來(lái)之后疲吸,它的top改變了距離座每, 從 10變成了 300,其他三個(gè)約束保持不變摘悴, 見(jiàn)下圖效果:

10.png

顯而易見(jiàn)峭梳, 除了top約束, 其他都沒(méi)有改變蹂喻! 也就是說(shuō)葱椭,約束被更新(相當(dāng)于系統(tǒng)升級(jí)一樣,是一個(gè)道理)

現(xiàn)在口四,我們通過(guò)UIButton的點(diǎn)擊事件來(lái)證明一下制作約束makeConstraintsupdateConstraints具體的區(qū)別在哪里孵运?

lazy var blackView = UIView()

override func viewDidLoad() {
    super.viewDidLoad()

    blackView.backgroundColor = UIColor.black
    view.addSubview(blackView)
    blackView.snp.makeConstraints { (make) in

        make.width.equalTo(100)
        make.height.equalTo(150)
        make.top.equalTo(50)
        make.centerX.equalToSuperview()
    }

    let btn = UIButton(type: .custom)
    btn.backgroundColor = UIColor.brown
    btn.frame = CGRect(x: 100, y: 200, width: 60, height: 30)
    btn.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
    view.addSubview(btn)

}

// 點(diǎn)擊更新/制作約束
func buttonAction() {

    blackView.snp.makeConstraints { (make) in
        make.width.height.equalTo(20)
        make.top.equalTo(300)
    }

}

先看效果圖

點(diǎn)擊事件發(fā)生前(圖1):

![Uploading 12_315832.png . . .]

點(diǎn)擊事件發(fā)生后(圖2)

12.png

圖3

13.png

圖4

14.png

上面,我們知道蔓彩,視圖 blackView一開(kāi)始是由四個(gè)約束確定位置和大小治笨,在點(diǎn)擊事情響應(yīng)后驳概,我們又給 blackView 制作(記住,是制作旷赖,而不是重做顺又,兩者有明確的區(qū)別)了3個(gè)約束,分別是 width等孵、height稚照、top, 那么這樣做問(wèn)題出現(xiàn)在哪里呢? 第一俯萌, 點(diǎn)擊事情發(fā)生前(圖1)果录, 在點(diǎn)擊事件發(fā)生后(見(jiàn)圖2), 我們發(fā)現(xiàn)咐熙,blackViewwidth弱恒、height約束改變了,但是 top卻沒(méi)有改變糖声,還是原來(lái)的距離父視圖頂部 50 的距離斤彼, 原因在于分瘦,我們?cè)谠瓉?lái)的約束基礎(chǔ)上又添加了多余的約束蘸泻, 也就是說(shuō),約束從4個(gè)變成了7個(gè)(見(jiàn)圖3左邊constraints)嘲玫, 這樣就產(chǎn)生了約束不明確悦施,進(jìn)而導(dǎo)致snapkit的警告(見(jiàn)圖4), 這樣布局顯然是不可取的去团,在項(xiàng)目中這樣做極其危險(xiǎn)抡诞,甚至可能會(huì)導(dǎo)致異常奔潰!M僚恪V绾埂!
現(xiàn)在鬼雀, 我們?cè)搶Ⅻc(diǎn)擊事件中的約束布局從makeConstraints改變成updateConstraints來(lái)試試兩者有什么區(qū)別(下面只添加了點(diǎn)擊事件的代碼顷窒,其他事重復(fù)的就不多此一舉了)

func buttonAction() {
    // 注意這里是updateConstraints, 而不是makeConstraints
    blackView.snp.updateConstraints { (make) in
        make.width.height.equalTo(20)
        make.top.equalTo(300)
    }
    print("這里試試snapkit有沒(méi)有報(bào)警告")
}

接著看點(diǎn)擊事件后的效果圖

圖5

15.png

圖6

16.png

圖7

17.png

發(fā)現(xiàn)沒(méi)有源哩,在將makeConstraints改變成updateConstraints之后鞋吉,約束還是4個(gè),snapkit沒(méi)有報(bào)警告励烦,點(diǎn)擊事件中的width谓着、height、top全部起了作用坛掠,而這就是兩者的本質(zhì)區(qū)別:makeConstraints是制作約束赊锚,在原來(lái)的基礎(chǔ)上再添加另外的約束治筒,也就是畫(huà)蛇添足,約束增加舷蒲,視圖布局就有不確定性矢炼,從而有些約束起作用,有些不起作用(如上面的top)阿纤,snapkit報(bào)警告>涔唷!欠拾!而updateConstraints是更新約束胰锌,改變?cè)屑s束,約束不會(huì)增加藐窄,沒(méi)經(jīng)過(guò)updateConstraints處理的保持原有約束资昧,經(jīng)過(guò)處理就更新約束,約束不會(huì)減少荆忍,snapkit不會(huì)產(chǎn)生警告格带,這是正常標(biāo)準(zhǔn)的更新約束的正確方式!I餐鳌叽唱!

  • 重做約束(remakeConstraints)
    重做約束的本質(zhì)就是:去掉已有的所有約束, 重新做約束微宝,記住棺亭,是做約束, 也就是說(shuō)蟋软, 使用了remakeConstraints后镶摘,重做的約束必須要能確定相應(yīng)視圖的大小和位置, 之前makeConstraints的約束已經(jīng)不會(huì)存在了,完全銷毀T朗亍F喔摇!
// 點(diǎn)擊更新/制作約束
func buttonAction() {

    // 注意這里是 remakeConstraints
    blackView.snp.remakeConstraints { (make) in
        make.width.height.equalTo(20)
        make.top.equalTo(300)
    }

    print("這里試試snapkit有沒(méi)有報(bào)警告")
}

效果圖

圖(1)

18.png

效果圖

圖(2)

19.png

圖(3)

20.png

我們看到湿痢, blackView重做了約束涝缝, 之前的約束不起任何作用,由于它在重做約束后只有 3 個(gè)約束分別是 width蒙袍、height俊卤、top, 但是這里有一個(gè)問(wèn)題,就是這 3 個(gè)約束只能確定大小害幅,無(wú)法確定視圖的位置消恍, 所以在水平方向上或者左右缺少一個(gè)布局條件, 故 blackView整體視圖的x緊靠左邊(默認(rèn))以现! 另外我們發(fā)現(xiàn)狠怨, 在圖(3)中约啊,右上角出現(xiàn)了一個(gè)感嘆號(hào)“!”, 那是因?yàn)楦嬖V你缺少了一個(gè)約束條件:x-xcode-debug-views://7f81fcbc7900: runtime: Layout Issues: Horizontal position is ambiguous for UIView.

小結(jié)

通過(guò)以上學(xué)習(xí)佣赖,我們或深或淺地學(xué)習(xí)了布局三方庫(kù)SnapKit的使用恰矩, 我相信,只要將上述布局會(huì)使用憎蛤,并且懂得布局的原則和道理外傅,基本上就可以“高枕無(wú)憂”了,至于涉及動(dòng)態(tài)布局俩檬、動(dòng)畫(huà)布局等知識(shí)萎胰,后續(xù)有時(shí)間會(huì)更新文檔。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末棚辽,一起剝皮案震驚了整個(gè)濱河市技竟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌屈藐,老刑警劉巖榔组,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異联逻,居然都是意外死亡搓扯,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)遣妥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)擅编,“玉大人,你說(shuō)我怎么就攤上這事箫踩。” “怎么了谭贪?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵境钟,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我俭识,道長(zhǎng)慨削,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任套媚,我火速辦了婚禮缚态,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘堤瘤。我一直安慰自己玫芦,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布本辐。 她就那樣靜靜地躺著桥帆,像睡著了一般医增。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上老虫,一...
    開(kāi)封第一講書(shū)人閱讀 51,688評(píng)論 1 305
  • 那天叶骨,我揣著相機(jī)與錄音,去河邊找鬼祈匙。 笑死忽刽,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的夺欲。 我是一名探鬼主播缔恳,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼洁闰!你這毒婦竟也來(lái)了歉甚?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤扑眉,失蹤者是張志新(化名)和其女友劉穎纸泄,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體腰素,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡聘裁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了弓千。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片衡便。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖洋访,靈堂內(nèi)的尸體忽然破棺而出镣陕,到底是詐尸還是另有隱情,我是刑警寧澤姻政,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布呆抑,位于F島的核電站,受9級(jí)特大地震影響汁展,放射性物質(zhì)發(fā)生泄漏鹊碍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一食绿、第九天 我趴在偏房一處隱蔽的房頂上張望侈咕。 院中可真熱鬧,春花似錦器紧、人聲如沸耀销。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)树姨。三九已至摩桶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間帽揪,已是汗流浹背硝清。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留转晰,地道東北人芦拿。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像查邢,于是被迫代替她去往敵國(guó)和親蔗崎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

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