Masonry源碼解讀

Masonry這個框架是使用代碼進行自動布局使用的钱烟,它的使用非常廣泛谍失,這段時間一直在學習這個框架眶俩,因此想把學到的東西記下來,方便以后查閱快鱼,也便于與人分享颠印。

自動布局約束的等式:

item1.attribute1 = multiplier × item2.attribute2 + constant

Masonry中使用了大量的點鏈式語法抹竹,考慮到應該有些小伙伴不知道點鏈式語法的來龍去脈线罕,因此這里先整理一下點鏈式語法

點鏈式語法

我們先來看一下Masonry框架的一種使用:

    [view mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(superview.mas_left).mas_offset(30);
    }];

上面的代碼是Masonry的簡單的使用窃判,這里面就用到了點鏈式語法make.left.equalTo(superview.mas_left).mas_offset(30);钞楼,我們看一下這句點鏈式語法,這里面包括三個要素:

  • 點語法:我們在訪問屬性的時候會使用點語法袄琳。
  • 小括號調(diào)用:在Objective-C中使用[ ]來調(diào)用方法询件,只有在調(diào)用Block的時候會使用(),因此這里我們可以使用Block來實現(xiàn)點鏈式語法中的()唆樊。
  • 連續(xù)調(diào)用:Block是有返回值的宛琅,那么我們可以在每次調(diào)用完Block后返回調(diào)用者對象本身,那么我們就可以實現(xiàn)連續(xù)的調(diào)用了逗旁。
    總結(jié)起來就是:

我們可以聲明一些Block類型的屬性嘿辟,讓block類型的屬性的返回值為其本身。

下面用一個計算器的例子來說明一下:

//Calculator.h
@interface Calculator : NSObject

//這里是創(chuàng)建一個屬性片效,屬性的類型是block類型仓洼,屬性名是add
@property (nonatomic, copy)Calculator * (^add)(NSInteger num);
@property (nonatomic, copy)Calculator * (^minus)(NSInteger num);
@property (nonatomic, copy)Calculator * (^multiply)(NSInteger num);
@property (nonatomic, copy)Calculator * (^divide)(NSInteger num);

@property (nonatomic, assign)NSInteger result;

@end
//Calculator.m
@implementation Calculator

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.result = 0;
    }
    
    return self;
}

//這里實現(xiàn)的是add這個屬性的get方法,只不過屬性的類型是block類型的堤舒。
- (Calculator * (^)(NSInteger num))add
{
    return ^id(NSInteger num){
        self.result += num;
        return self;
    };
}

- (Calculator * (^)(NSInteger num))minus
{
    return ^id(NSInteger num){
        self.result -= num;
        return self;
    };
}

- (Calculator * (^)(NSInteger num))multiply
{
    return ^id(NSInteger num){
        self.result *= num;
        return self;
    };
}

- (Calculator * (^)(NSInteger num))divide
{
    return ^id(NSInteger num){
        self.result /= num;
        return self;
    };
}

@end

調(diào)用:

    Calculator *calculator = [[Calculator alloc] init];
    calculator.add(5).minus(8).multiply(8).divide(23);
  • 1.calculator.add是調(diào)用了add屬性的get方法色建,這個方法會返回一個block,block如下:
    return ^id(NSInteger num){
        self.result += num;
        return self;
    };
  • 2.calculator.add(5)會執(zhí)行這個block舌缤,這個block的返回值是Calculator對象本身箕戳,所以calculator.add(5)執(zhí)行完了得到的是一個Calculator對象某残。
  • 3.Calculator對象繼續(xù)訪問minus屬性,執(zhí)行minus屬性的get方法陵吸。
更簡潔的實現(xiàn)

上面是通過聲明一系列的block類型的屬性玻墅,再實現(xiàn)block屬性的get方法來實現(xiàn)鏈式調(diào)用,但是Masonry的實現(xiàn)方式和這種方式還是有區(qū)別壮虫,我們在Masonry中并沒有發(fā)現(xiàn)Block類型的屬性的聲明澳厢,反而是看到了一些平時見的比較少的方法的聲明:

0D223676-9F5F-4D4E-AAE0-05FA01F25A5F.png
也就是說Masonry中是把Block類型的屬性改成了返回值為Block類型的方法,這樣也能成功實現(xiàn)鏈式語法囚似,這是為什么呢剩拢?
回想一下,當我們通過點語法去訪問屬性的時候?qū)嵸|(zhì)上就是訪問了get方法饶唤,那么當不存在一個名為name的屬性時徐伐,我們使用self.name去訪問時是不是也會跑去執(zhí)行名為name的方法呢?答案是肯定的募狂,也就是只要我們申明了一個xxx方法办素,那就可以放心的寫self.xxx。
所以最終Calculator.h文件就改成了這樣:

@interface Calculator : NSObject
/*
@property (nonatomic, copy)Calculator * (^add)(NSInteger num);
@property (nonatomic, copy)Calculator * (^minus)(NSInteger num);
@property (nonatomic, copy)Calculator * (^multiply)(NSInteger num);
@property (nonatomic, copy)Calculator * (^divide)(NSInteger num);
@property (nonatomic, assign)NSInteger result;
*/
- (Calculator * (^)(NSInteger num))add;
- (Calculator * (^)(NSInteger num))minus;
- (Calculator * (^)(NSInteger num))multiply;
- (Calculator * (^)(NSInteger num))divide;

@end

Masonry的使用方法

1.使用MASConstraintMaker創(chuàng)建約束
UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo(superview.mas_top).with.offset(padding.top); //with is an optional semantic filler
    make.left.equalTo(superview.mas_left).with.offset(padding.left);
    make.bottom.equalTo(superview.mas_bottom).with.offset(-padding.bottom);
    make.right.equalTo(superview.mas_right).with.offset(-padding.right);
}];

或者更簡單的方法:

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(superview).with.insets(padding);
}];
并不是只有equalTo即等于這一種關(guān)系祸穷,還可以有:

lessThanOrEqualTo:等同于NSLayoutRelationLessThanOrEqual
greaterThanOrEqualTo:等同于NSLayoutRelationGreaterThanOrEqual

2.MASViewAttribute

Masonry中有MASViewAttribute這個類性穿,這個類就等同于NSLayoutAttribute這個類:

MASViewAttribute NSLayoutAttribute
view.mas_left NSLayoutAttributeLeft
view.mas_right NSLayoutAttributeRight
view.mas_top NSLayoutAttributeTop
view.mas_bottom NSLayoutAttributeBottom
view.mas_leading NSLayoutAttributeLeading
view.mas_trailing NSLayoutAttributeTrailing
view.mas_width NSLayoutAttributeWidth
view.mas_height NSLayoutAttributeHeight
view.mas_centerX NSLayoutAttributeCenterX
view.mas_centerY NSLayoutAttributeCenterY
view.mas_baseline NSLayoutAttributeBaseline
3.與常數(shù)有關(guān)的問題

自動布局不允許對齊的屬性如left,right雷滚,centerY等設置為常數(shù)需曾,如果我們傳了一個常數(shù)給這些屬性,Masonry會自動把這些約束變?yōu)橄鄬τ诟敢晥D的約束揭措,即:

//creates view.left = view.superview.left + 10
make.left.equalTo(@10)

4.mas前綴相關(guān)

在使用Masonry的時候,有時候會比較迷糊什么時候使用帶有mas前綴的刻蚯,什么時候使用不帶前綴的绊含,我們看下面這句代碼:

make.top.mas_equalTo(42);

這句代碼也可以這樣寫:

make.top.equalTo(@42);

但是這樣寫就會報錯:

make.top.equalTo(42);

原因就在于這個括號里面的參數(shù)類型必須是id類型,如果括號里面的參數(shù)不傳id類型就傳常量類型也行炊汹,那么就必須要在equalTo前面加上mas躬充,加上mas后,mas_equalTo會把傳進來的數(shù)值類型變成id類型讨便。

5.MASCompositeConstraint類相關(guān)

Masonry給了我們幾個便利的方法來讓我們一次性創(chuàng)建多個約束充甚,Masonry中與這個約束相關(guān)的類是MASCompositeConstraint類,簡單使用如下:
edges

// make top, left, bottom, right equal view2
make.edges.equalTo(view2);

// make top = superview.top + 5, left = superview.left + 10,
//      bottom = superview.bottom - 15, right = superview.right - 20
make.edges.equalTo(superview).insets(UIEdgeInsetsMake(5, 10, 15, 20))

size

// make width and height greater than or equal to titleLabel
make.size.greaterThanOrEqualTo(titleLabel)

// make width = superview.width + 100, height = superview.height - 50
make.size.equalTo(superview).sizeOffset(CGSizeMake(100, -50))

center

// make centerX and centerY = button1
make.center.equalTo(button1)

// make centerX = superview.centerX - 5, centerY = superview.centerY + 10
make.center.equalTo(superview).centerOffset(CGPointMake(-5, 10))
6.修改已經(jīng)存在的約束

當我們只是修改約束的constant的時候霸褒,可以使用mas_updateConstraints:

// this is Apple's recommended place for adding/updating constraints
// this method can get called multiple times in response to setNeedsUpdateConstraints
// which can be called by UIKit internally or in your code if you need to trigger an update to your constraints
- (void)updateConstraints {
    [self.growingButton mas_updateConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(self);
        make.width.equalTo(@(self.buttonSize.width)).priorityLow();
        make.height.equalTo(@(self.buttonSize.height)).priorityLow();
        make.width.lessThanOrEqualTo(self);
        make.height.lessThanOrEqualTo(self);
    }];

    //according to apple super should be called at end of method
    [super updateConstraints];
}

當我們要修改的不止是約束的constant的時候伴找,使用mas_updateConstraints就力不從心了,這時就需要使用mas_remakeConstraints:

- (void)changeButtonPosition {
    [self.button mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.size.equalTo(self.buttonSize);

        if (topLeft) {
            make.top.and.left.offset(10);
        } else {
            make.bottom.and.right.offset(-10);
        }
    }];
}
休息一下

解讀源碼

我們在解讀源碼的時候先從最簡單最基礎的使用開始废菱,然后由淺入深技矮,逐漸深入抖誉。下面我們先分析一下整個框架的文件結(jié)構(gòu):

E4C13061-A282-4C44-9626-B797EE011C74.png

下面就從一個最簡單最基本的使用開始來探究源碼:

    [view mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(superview.mas_left).mas_offset(30);
    }];

我們先不管外面的方法調(diào)用,只需要知道m(xù)ake是MASConstraintMaker類型的就行了衰倦,從make.left.equalTo(superview.mas_left).mas_offset(30);開始:

  • 1.make.left
    left是它的一個屬性袒炉,這里調(diào)用的是屬性的getter方法。
    57BE757D-EE05-47E3-9F2D-4A58A3F2712A.png
    繼續(xù)往下查看:
    668FACAD-700E-4583-82AB-867A76F46A5D.png
    再繼續(xù):
    20ED5488-141A-442A-A8D5-3A7798A4486F.png
    我們來看一下MASViewConstraint對象的創(chuàng)建:
    2728C00E-9170-4905-BCB0-82CD9C91ACAF.png

那么現(xiàn)在我們來總結(jié)一下make.left做了哪些事:

make.left是調(diào)用了MASConstraintMaker類的left屬性的get方法樊零,這里創(chuàng)建了一個MASViewAttribute對象我磁,這個對象由一個UIView對象和一個NSLayoutAttribute來創(chuàng)建,這里UIView對象是view驻襟,NALayoutAttribute為NSLayoutAttributeLeft夺艰,所以這里MASViewAttribute對象也就是封裝了約束等號左邊的兩個元素。塑悼。然后使用創(chuàng)建的MASViewAttribute對象來創(chuàng)建了一個MASViewConstraint對象劲适,這個對象代表這一行代碼所表示的整個約束。最終make.left返回了一個MASVIewConstraint對象厢蒜。

需要注意的是霞势,MASConstraintMaker對象有一個數(shù)組類型的consrtaints屬性,新創(chuàng)建的MASViewConstraint對象被加入到了這個屬性中斑鸦,在最后添加約束的時候會遍歷這個數(shù)組愕贡。

  • 2.superview.mas_left
    mas_left是分類的一個屬性,所以superview.mas_left會調(diào)用分類的-(MASViewAttribute *)mas_left方法巷屿。
    9413264B-AB4F-4F1B-921A-153DE3B96E93.png

    這里通過代碼創(chuàng)建了一個MASViewAttribute對象固以,對象的view即superview,對象的attribute即NSLayoutAttributeLeft嘱巾,我們看看是如何創(chuàng)建的:
    892F2158-3377-4352-8EFF-B5937A412744.png

    總結(jié)一下:

superview.mas_left返回了一個MASViewAttribute對象憨琳,這個對象封裝了約束等號右邊的兩個元素。

  • 3.make.left.equalTo(superview.mas_left)
    進入equalTo查看具體實現(xiàn):
    F8189FD9-D511-48B3-95B5-CBA04C2DE78C.png
    也就是說我執(zhí)行make.left.equalTo會得到一個Block旬昭,那么我執(zhí)行make.left.equalTo(superview.mas_left)就是執(zhí)行這個Block篙螟,即make.left.equalTo(superview.mas_left)會執(zhí)行self.equalToWithRelation(attribute, NSLayoutRelationEqual)這一行核心代碼,并返回這一行核心代碼的返回值问拘。
    由于make.left是MASViewConstraint對象遍略,所以我們要去MASViewConstraint類中查看equalWithRelation的實現(xiàn):
    4D84193E-0A50-425E-8CF8-297CCB1B53B8.png
    self.secondViewAttribute = attribute;會觸發(fā)secondViewAttribute這個屬性的set方法,我們看一下其set方法的實現(xiàn):
    1C0A9CAA-0874-49C3-9E93-F126A4428219.png
    這里的意思就是make.left.equalTo()這個括號里面?zhèn)魅氲臇|西可能有三種情況骤坐,第一種是數(shù)字绪杏,第二種是一個UIView對象,如果是UIView對象纽绍,那就將其layoutAttribute設置為何firstAttribute一致,也就是我們也可以這樣寫:make.left.equalTo(superview)蕾久,這樣Masonry也能成功識別。第三種是傳入的MASViewConstraint對象拌夏,如果傳入這種對象則可以直接賦值給secondViewAttribute屬性腔彰。
    下面我們再來看一下第一種情況傳入數(shù)字的處理方式叫编,我們進入setLayoutConstantWithValue:這個方法:
    B7C31203-51F7-4E48-80ED-4F3B58AC9D31.png
    代碼里面設置offset,centerOffset等都不是真正的實現(xiàn)霹抛,真正的實現(xiàn)在offset屬性的set方法里搓逾,我們要其MASViewConstraint類中找offset屬性的set方法:
    C66A8756-CD7D-418C-838F-4130A72E8A0E.png
    總結(jié)起來就是如果傳入的是數(shù)值類型,那么就給MASViewConstraint的layoutConstant屬性賦值杯拐。

這樣我們就清楚了make.left.equalTo()這個括號中傳入各種不同類型的值會怎么操作霞篡。

總結(jié)一下make.left.equalTo(superview.mas_left)做的事情:

make.left創(chuàng)建了一個firstViewAttribute,firstViewAttribute的view屬性即為
mas_makeConstraint方法的調(diào)用者,其layoutAttribute屬性為NSLayoutAttributeLeft端逼,firstViewAttribute封裝了約束等式左邊的兩個item朗兵。接著通過傳入firstViewAttribute創(chuàng)建了一個MASViewConstraint對象。superview.mas_left則是創(chuàng)建了一個secondViewAttribute對象顶滩,該對象的view即為superview余掖,layoutAttributeNSLayoutAttributeLeftmake.left.equalTo(supervie.mas_left)則是將secondViewAttribute賦值給MASViewConstraint對象的secondViewAttribute屬性礁鲁,并給MASViewConstraint對象的layoutRelation屬性賦值盐欺。

  • 4..mas_offset(30)
    mas_offset的顏色是土黃色,說明這是一個宏定義仅醇,我們點進去冗美,發(fā)現(xiàn)這個宏定義是定義在MASConstraint.h文件中:
#define mas_offset(...)                  valueOffset(MASBoxValue((__VA_ARGS__)))

這不是一個簡單的宏定義,里面還進行了嵌套析二,我們看一下MASBoxValue()方法做了什么粉洼,在MASUtilities.h這個文件中找到了MASBoxValue()這個方法:

AF2FEF9E-81D3-4CAC-A6AB-79BBED81485C.png
從圖中我們可以看到,這個方法就是把一些數(shù)值類型的值轉(zhuǎn)為id類型叶摄。

Masonry的用法這部分我說過mas前綴的使用属韧,這里我們就看到了其實現(xiàn)方法。如果我們括號里想要直接傳入數(shù)值類型而不是id類型的參數(shù)蛤吓,那么前面使用的API就必須帶mas前綴宵喂,否則報錯,如果傳入的是id類型柱衔,則前面使用的API是否帶mas前綴均可樊破。

所以.mas_offset(30)也就等于.valueOffset(@30)愉棱,那么我們來查看一下MASConstraint.m中的實現(xiàn):

9EDB3756-844B-48C8-BF55-1DF70D10A560.png
最終就是設置了MASViewConstraint的layoutConstant屬性:
85F60147-C2E5-4A0B-9AB7-E96B8BD51130.png

到這里make.left.equalTo(superview.mas_left).mas_offset(30);這行代碼就全解讀完了唆铐。總結(jié)一下就是:

make,left創(chuàng)建了一個MASViewConstraint對象奔滑,為這個對象的firstViewAttribute屬性賦值艾岂,superview.mas_left即創(chuàng)建了一個MASViewAttribute對象,equalTo()即把這個MASViewAttribute對象賦值給MASViewConstraint對象的secondViewAttribute屬性朋其,.mas_offset(30)則是給MASViewConstraint對象的layoutConstant屬性賦值為30.

  • 5.mas_makeConstraints:
    mas_makeConstraints:這個方法是在UIView的分類中定義并實現(xiàn)的王浴,下面我們看一下其具體實現(xiàn):
    48B3AC46-BE1A-4FEE-98E2-252900F394F3.png
    72B1DEFF-9089-41C5-A215-C070C0781C33.png

    再來看[constraint install]:脆炎,這個方法的內(nèi)容比較多,我們分兩部分來看:
    0735EF28-E952-4C4F-8F20-7DA742D42D64.png
    C50DD5C3-64C0-4E40-86F2-B18311F7979C.png

    到這里約束就添加完成了氓辣。 總結(jié)一下添加約束的大體流程:

首先根據(jù)MASViewConstraint對象的firstViewAttributesecondViewAttribute這兩個屬性秒裕,訪問這兩個屬性得到firstLayoutItemfirstLayoutAttribute钞啸。secondLayoutitem几蜻,secondLayoutAttribute。然后處理有時是對齊屬性如left沒有提供view的情況体斩,這時就要設置view為其父視圖梭稚。然后尋找應該將約束添加到哪個視圖上,最后添加約束到對應的視圖上絮吵。

休息一下

組合約束(MASCompositeConstraint)

Masonry中可以直接約束size弧烤,center,edge這樣的組合約束蹬敲。其本質(zhì)也就是把它拆成多個單個約束暇昂,比如對size的約束,就是拆成width和height這兩個約束粱栖。下面我們看一下其具體的實現(xiàn)方法:

make.size.equalTo(superview).sizeOffset(CGSizeMake(10, 10));
  • 1.make.size
    44B0B9CD-B912-44A6-8C8B-F07275FDFAE9.png
    繼續(xù)往下看:- (MASConstraint *)addConstraintWithAttributes:(MASAttribute)attrs方法:
    081C430A-BD90-4FC8-9D62-4FDC07D0EA6B.png

    總結(jié)一下make.size做了哪些事:

把size這一個拆分成了width和height這兩個话浇,根據(jù)這兩個約束創(chuàng)建了兩個MASViewConstraint對象,裝到一個數(shù)組里面闹究,使用這個數(shù)組來創(chuàng)建了一個MASCompositeConstraint對象幔崖,最后返回這個MASCompositeConstraint對象。

  • 2..equalTo(superview)
    D5C22579-A50F-44BC-A79B-5815FB5FC96D.png
    繼續(xù):
    5FDF1EB1-ED9A-4AD4-8EA8-B935A7AF5D5F.png

    總結(jié)一下make.size.equalTo(superview):

把size這一個約束拆分成了width和height這兩個約束渣淤,并根據(jù)此創(chuàng)建了兩個MASViewConstraint對象赏寇,根據(jù)這兩個對象組成的數(shù)組去創(chuàng)建一個MASCompositeConstraint對象。然后遍歷MASCompositeConstraint對象的childConstraints數(shù)組价认,取出數(shù)組里面的額每個MASViewConstraint對象嗅定,然后像處理單個MASViewConstraint一樣去處理。

  • 3..sizeOffset(CGSizeMake(10, 10))
    可以想象就是把它拆分用踩,然后賦值給兩個MASViewConstraint的layoutConstant屬性渠退,就不詳細說了。

mas_updateConstraints:和mas_remakeConstraints:

自動布局約束等式:
item1.attribute1 = multiplier × item2.attribute2 + constant

有時候我們有更改約束的需求脐彩,比如我們要做一個動畫碎乃,移動某個視圖,那就需要改變視圖約束惠奸,當我們只是改變約束的constant時梅誓,可以使用mas_updateConstraints:這個方法。而當我們需要改變的不止constant時,就需要調(diào)用mas_remakeConstraints:這個方法了梗掰。

先來看一下mas_updateConstraints:這個方法是怎么實現(xiàn)只改變約束的constant的:

CEDE51E1-CB87-42C7-9E40-A3AFA01A4755.png

進入[constraintMaker install]
99A0DCCC-96D2-455F-B0E2-EE71B5745FD0.png

看看[constraint install]中是怎么實現(xiàn)的:
2CE11985-5A8F-4701-939C-AB16EA8B56EA.png

總結(jié)起來嵌言,mas_updateConstraints:就是去self.installedView.constarints這個屬性數(shù)組中去遍歷,看有沒有這樣一個NSLayoutConstraint對象及穗,它除了constant外摧茴,所有內(nèi)容都和當前的NSLayoutConstraint對象一致,如果有這個對象埂陆,那么就把該對象的constant改為當前NSLayoutConstraint對象的constant蓬蝶。這樣來完成約束條件的更新。

再來看一下mas_remakeConstraints:
當我們要改變的約束條件不止是constant這么簡單時猜惋,使用mas_remakeConstraints:就不頂用了丸氛,就要使用mas_remakeConstraints:這個方法。

F6106353-8D44-4F85-BE0C-1E8E8CE7D9A0.png
再看[constraintMaker install]:
5D7151E9-43FE-4E11-8AB2-CE965A40B190.png

7AAA699D-C641-48AD-83D8-DA855ADE7437.png

這篇文章在簡書的地址:http://www.reibang.com/p/8990c5a98d29

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末著摔,一起剝皮案震驚了整個濱河市缓窜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谍咆,老刑警劉巖禾锤,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異摹察,居然都是意外死亡恩掷,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門供嚎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來黄娘,“玉大人,你說我怎么就攤上這事克滴”普” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵劝赔,是天一觀的道長誓焦。 經(jīng)常有香客問我,道長着帽,這世上最難降的妖魔是什么杂伟? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮仍翰,結(jié)果婚禮上赫粥,老公的妹妹穿的比我還像新娘。我一直安慰自己歉备,他們只是感情好傅是,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布匪燕。 她就那樣靜靜地躺著蕾羊,像睡著了一般喧笔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上龟再,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天书闸,我揣著相機與錄音,去河邊找鬼利凑。 笑死浆劲,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的哀澈。 我是一名探鬼主播牌借,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼割按!你這毒婦竟也來了膨报?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤适荣,失蹤者是張志新(化名)和其女友劉穎现柠,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體弛矛,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡够吩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了丈氓。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片周循。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖万俗,靈堂內(nèi)的尸體忽然破棺而出鱼鼓,到底是詐尸還是另有隱情,我是刑警寧澤该编,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布迄本,位于F島的核電站,受9級特大地震影響课竣,放射性物質(zhì)發(fā)生泄漏嘉赎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一于樟、第九天 我趴在偏房一處隱蔽的房頂上張望公条。 院中可真熱鬧,春花似錦迂曲、人聲如沸靶橱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽关霸。三九已至传黄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間队寇,已是汗流浹背膘掰。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留佳遣,地道東北人识埋。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像零渐,于是被迫代替她去往敵國和親窒舟。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

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