iOS-Block本質(zhì)

參考篇:iOS-Block淺談

前言:本文簡述Block本質(zhì)把还,如有錯誤請留言指正均驶。

第一部分:Block本質(zhì)

Q:什么是Block届囚,Block的本質(zhì)是什么婴噩?

  • block本質(zhì)上也是一個OC對象,它內(nèi)部也有個isa指針
  • block是封裝了函數(shù)調(diào)用以及函數(shù)調(diào)用環(huán)境的OC對象
  • block是封裝函數(shù)及其上下文的OC對象
block底層結(jié)構(gòu)圖

查看block源碼:

struct __block_impl {
    void *isa;
    int Flags;
    int Reserved;
    void *FuncPtr;
};

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  // 構(gòu)造函數(shù)(類似于OC的init方法)瞒御,返回結(jié)構(gòu)體對象
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

// 封裝了block執(zhí)行邏輯的函數(shù)
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {

            NSLog((NSString *)&__NSConstantStringImpl__var_folders_2r__m13fp2x2n9dvlr8d68yry500000gn_T_main_c60393_mi_0);
        }

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
        // 定義block變量
        void (*block)(void) = &__main_block_impl_0(
                                                   __main_block_func_0,
                                                   &__main_block_desc_0_DATA
                                                   );

        // 執(zhí)行block內(nèi)部的代碼
        block->FuncPtr(block);
    }
    return 0;
}
clang查看Block
  • FuncPtr:指向調(diào)用函數(shù)的地址
  • __main_block_desc_0 :block描述信息
  • Block_size:block的大小

第二部分:Block捕獲變量

Q:下述代碼輸出值為多少父叙?

int age=10;
void (^Block)(void) = ^{
    NSLog(@"age:%d",age);
};
age = 20;
Block();

輸出值為 age:10
原因:創(chuàng)建block的時候,已經(jīng)把age的值存儲在里面了肴裙。

Q:下列代碼輸出值分別為多少趾唱?

auto int age = 10;
static int num = 25;
void (^Block)(void) = ^{
    NSLog(@"age:%d,num:%d",age,num);
};
age = 20;
num = 11;
Block();

輸出結(jié)果為:age:10,num:11
愿意:auto變量block訪問方式是值傳遞,static變量block訪問方式是指針傳遞
源碼證明:

int age = __cself->age; // bound by copy
int *num = __cself->num; // bound by copy

NSLog((NSString *)&__NSConstantStringImpl__var_folders_2r__m13fp2x2n9dvlr8d68yry500000gn_T_main_d2875b_mi_0, age, (*num));

int age = 10;
static int num = 25;

block = ((void (*)())&__test_block_impl_0((void *)__test_block_func_0, &__test_block_desc_0_DATA, age, &num));

age = 20;
num = 11;

上述代碼可查看 static修飾的變量蜻懦,是根據(jù)指針訪問的

Q:為什么block對auto和static變量捕獲有差異甜癞?

auto自動變量可能會銷毀的,內(nèi)存可能會消失宛乃,不采用指針訪問悠咱;static變量一直保存在內(nèi)存中,指針訪問即可

Q:block對全局變量的捕獲方式是征炼?

block不需要對全局變量捕獲析既,都是直接采用取值的

Q:為什么局部變量需要捕獲?

考慮作用域的問題谆奥,需要跨函數(shù)訪問眼坏,就需要捕獲

Q:block的變量捕獲(capture)

為了保證block內(nèi)部能夠正常訪問外部的變量,block有個變量捕獲機制


block的變量捕獲

Q:block里訪問self是否會捕獲酸些?

會宰译,self是當(dāng)調(diào)用block函數(shù)的參數(shù)檐蚜,參數(shù)是局部變量,self指向調(diào)用者

Q:block里訪問成員變量是否會捕獲囤屹?

會熬甚,成員變量的訪問其實是self->xx,先捕獲self肋坚,再通過self訪問里面的成員變量

第三部分 Block類型

Q:block有哪幾種類型乡括?

block的類型,取決于isa指針智厌,可以通過調(diào)用class方法或者isa指針查看具體類型诲泌,最終都是繼承自NSBlock類型

  • __NSGlobalBlock __ ( _NSConcreteGlobalBlock )
  • __NSStackBlock __ ( _NSConcreteStackBlock )
  • __NSMallocBlock __ ( _NSConcreteMallocBlock )

代碼示例

void (^block1)(void) = ^{
    NSLog(@"block1");
};
NSLog(@"%@",[block1 class]);
NSLog(@"%@",[[block1 class] superclass]);
NSLog(@"%@",[[[block1 class] superclass] superclass]);
NSLog(@"%@",[[[[block1 class] superclass] superclass] superclass]);
NSLog(@"%@",[[[[[block1 class] superclass] superclass] superclass] superclass]);

輸出結(jié)果:
NSGlobalBlock
__NSGlobalBlock
NSBlock
NSObject
null

上述代碼輸出了block1的類型,也證實了block是對象铣鹏,最終繼承NSObject

代碼展示block的三種類型:

int age = 1;
void (^block1)(void) = ^{
    NSLog(@"block1");
};

void (^block2)(void) = ^{
    NSLog(@"block2:%d",age);
};

NSLog(@"%@/%@/%@",[block1 class],[block2 class],[^{
    NSLog(@"block3:%d",age);
} class]);

輸出結(jié)果:
__NSGlobalBlock __/__NSMallocBlock __/__NSStackBlock __

Q:各類型的block在內(nèi)存中如何分配的敷扫?

  • __NSGlobalBlock __ 在數(shù)據(jù)區(qū)
  • __NSMallocBlock __ 在堆區(qū)
  • __NSStackBlock __ 在棧區(qū)
  • 堆:動態(tài)分配內(nèi)存,需要程序員自己申請诚卸,程序員自己管理
  • 棧:自動分配內(nèi)存葵第,自動銷毀,先入后出合溺,棧上的內(nèi)容存在自動銷毀的情況
block內(nèi)存分配

Q:如何判斷block是哪種類型卒密?

  • 沒有訪問auto變量的block是__NSGlobalBlock __ ,放在數(shù)據(jù)段
  • 訪問了auto變量的block是__NSStackBlock __
  • [__NSStackBlock __ copy]操作就變成了__NSMallocBlock __

Q:對每種類型block調(diào)用copy操作后是什么結(jié)果棠赛?

  • __NSGlobalBlock __ 調(diào)用copy操作后哮奇,什么也不做
  • __NSStackBlock __ 調(diào)用copy操作后,復(fù)制效果是:從棧復(fù)制到堆睛约;副本存儲位置是
  • __NSMallocBlock __ 調(diào)用copy操作后鼎俘,復(fù)制效果是:引用計數(shù)增加;副本存儲位置是

Q:在ARC環(huán)境下辩涝,編譯器會根據(jù)情況自動將棧上的block復(fù)制到堆上的幾種情況贸伐?

  • 1.block作為函數(shù)返回值時
  • 2.將block賦值給__strong指針時
  • 3.block作為Cocoa API中方法名含有usingBlock的方法參數(shù)時
  • 4.block作為GCD API的方法參數(shù)時

MRC下block屬性的建議寫法
@property (copy, nonatomic) void (^block)(void);

ARC下block屬性的建議寫法
@property (copy, nonatomic) void (^block)(void);

第四部分:對象類型的auto變量

Q:ARC下述代碼中Person對象是否會釋放?

示例代碼:

typedef void(^XBTBlock)(void);
XBTBlock block;
{
    Person *p = [[Person alloc] init];
    p.age = 10;
    
    block = ^{
        NSLog(@"======= %d",p.age);
    };
}

Person.m
- (void)dealloc{
    NSLog(@"Person - dealloc");
}

輸出結(jié)果:不會打印Person - dealloc
轉(zhuǎn)化C++代碼后:

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  Person *person;
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, MJPerson *__strong _person, int flags=0) : person(_person) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

上述
block為堆block怔揩,block里面有一個Person指針棍丐,Person指針指向Person對象。只要block還在沧踏,Person就還在。block強引用了Person對象巾钉。

Q:上述代碼改換成MRC翘狱,Person對象會釋放么?

會的砰苍!
堆空間的block會對Person對象retain操作潦匈,擁有一次Person對象阱高。

Q:下列代碼中Person是否會被釋放?

@autoreleasepool {
        XBTBlock block;
        
        {
            Person *p = [[Person alloc] init];
            p.age = 10;
            __weak Person *weakPersn = p;
            block = ^{
                NSLog(@"======= %d",weakPersn.age);
            };
        }
        NSLog(@"--------------");
}

答案:會釋放

小結(jié)

無論MRC還是ARC茬缩,棾嗑空間上的block,不會持有對象凰锡;堆空間的block未舟,會持有對象。

Q:當(dāng)block內(nèi)部訪問了對象類型的auto變量時掂为,是否會強引用裕膀?

答案:分情況討論,分為棧block和堆block

棧block
a) 如果block是在棧上勇哗,將不會對auto變量產(chǎn)生強引用
b) 棧上的block隨時會被銷毀昼扛,也沒必要去強引用其他對象

堆block
1.如果block被拷貝到堆上:
a) 會調(diào)用block內(nèi)部的copy函數(shù)
b) copy函數(shù)內(nèi)部會調(diào)用_Block_object_assign函數(shù)
c) _Block_object_assign函數(shù)會根據(jù)auto變量的修飾符(__strong、__weak欲诺、__unsafe_unretained)做出相應(yīng)的操作抄谐,形成強引用(retain)或者弱引用

2.如果block從堆上移除
a) 會調(diào)用block內(nèi)部的dispose函數(shù)
b) dispose函數(shù)內(nèi)部會調(diào)用_Block_object_dispose函數(shù)
c) _Block_object_dispose函數(shù)會自動釋放引用的auto變量(release)

正確答案:

  • 如果block在空間,不管外部變量是強引用還是弱引用扰法,block都會弱引用訪問對象
  • 如果block在空間蛹含,如果外部強引用,block內(nèi)部也是強引用迹恐;如果外部弱引用挣惰,block內(nèi)部也是弱引用

Q:__weak 在使用clang轉(zhuǎn)換OC為C++代碼時,可能會遇到以下問題cannot create __weak reference in file using manual reference

解決方案:支持ARC殴边、指定運行時系統(tǒng)版本憎茂,比如
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 main.m

Q1:gcd的block中引用 Person對象什么時候銷毀?

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    Person *person = [[Person alloc] init];
    person.age = 10;
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"age:%d",person.age);
    });
    
    NSLog(@"touchesBegan");
}

輸出結(jié)果:
14:36:03.395120+0800 test[1032:330314] touchesBegan
14:36:05.395237+0800 test[1032:330314] age:10
14:36:05.395487+0800 test[1032:330314] Person-dealloc

原因:gcd的block默認(rèn)會做copy操作锤岸,即dispatch_after的block是堆block竖幔,block會對Person強引用,block銷毀時候Person才會被釋放是偷。

Q2:上述代碼如果換成__weak拳氢,Person什么時候釋放?

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    Person *person = [[Person alloc] init];
    person.age = 10;
    
    __weak Person *weakPerson = person;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"age:%p",weakPerson);
    });

    NSLog(@"touchesBegan");
}

輸出結(jié)果:
14:38:42.996990+0800 test[1104:347260] touchesBegan
14:38:42.997481+0800 test[1104:347260] Person-dealloc
14:38:44.997136+0800 test[1104:347260] age:0x0

原因:使用__weak修飾過后的對象蛋铆,堆block會采用弱引用馋评,無法延時Person的壽命,所以在touchesBegan函數(shù)結(jié)束后刺啦,Person就會被釋放留特,gcd就無法捕捉到Person。

Q3:如果gcd內(nèi)包含gcd,Person會什么時候釋放蜕青?

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    Person *person = [[Person alloc] init];
    person.age = 10;
    
    __weak Person *weakPerson = person;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4.0 * NSEC_PER_SEC)),
                   dispatch_get_main_queue(), ^{
                       
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"2-----age:%p",person);
        });
        NSLog(@"1-----age:%p",weakPerson);
    });

    NSLog(@"touchesBegan");
}

輸出結(jié)果:
14:48:01.293818+0800 test[1199:403589] touchesBegan
14:48:05.294127+0800 test[1199:403589] 1-----age:0x604000015eb0
14:48:08.582807+0800 test[1199:403589] 2-----age:0x604000015eb0
14:48:08.583129+0800 test[1199:403589] Person-dealloc

原因:gcd內(nèi)部只要有強引用Person苟蹈,Person就會等待執(zhí)行完再銷毀!所以Person銷毀時間為7秒右核。

Q4:如果gcd內(nèi)部先強引用后弱引用慧脱,Person什么時候釋放?

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    Person *person = [[Person alloc] init];
    person.age = 10;
    
    __weak Person *weakPerson = person;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4.0 * NSEC_PER_SEC)),
                   dispatch_get_main_queue(), ^{
                       
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"2-----age:%p",weakPerson);
        });
        NSLog(@"1-----age:%p",person);
    });

    NSLog(@"touchesBegan");
}

輸出結(jié)果
14:52:29.036878+0800 test[1249:431302] touchesBegan
14:52:33.417862+0800 test[1249:431302] 1-----age:0x6000000178d0
14:52:33.418178+0800 test[1249:431302] Person-dealloc
14:52:36.418204+0800 test[1249:431302] 2-----age:0x0

原因:Person會等待強引用執(zhí)行完畢后釋放贺喝,只要強引用執(zhí)行完菱鸥,就不會等待后執(zhí)行的弱引用,會直接釋放的搜变,所以Person釋放時間為4秒采缚。

第五部分:__block修飾符

Q:block在修改NSMutableArray,需不需要添加__block挠他?

不需要扳抽。

Q:block能否修改變量值?

auto修飾變量殖侵,block無法修改贸呢,因為block使用的時候是內(nèi)部創(chuàng)建了變量來保存外部的變量的值,block只有修改內(nèi)部自己變量的權(quán)限拢军,無法修改外部變量的權(quán)限楞陷。
static修飾變量,block可以修改茉唉,因為block把外部static修飾變量的指針存入固蛾,block直接修改指針指向變量值,即可修改外部變量值度陆。
全局變量值艾凯,全局變量無論哪里都可以修改,當(dāng)然block內(nèi)部也可以修改懂傀。

Q:__block int age = 10趾诗,系統(tǒng)做了哪些?

答案:編譯器會將__block變量包裝成一個對象
查看c++源碼:

struct __Block_byref_age_0 {
  void *__isa;
__Block_byref_age_0 *__forwarding;//age的地址
 int __flags;
 int __size;
 int age;//age 的值
};

Q:__block 修飾符作用蹬蚁?

  • __block可以用于解決block內(nèi)部無法修改auto變量值的問題
  • __block不能修飾全局變量恃泪、靜態(tài)變量(static)
  • 編譯器會將__block變量包裝成一個對象
  • __block修改變量:age->__forwarding->age
  • __Block_byref_age_0結(jié)構(gòu)體內(nèi)部地址和外部變量age是同一地址
__forwarding指針指向

Q:block可以向NSMutableArray添加元素么?

NSMutableArray *arr = [NSMutableArray array];

Block block = ^{
    [arr addObject:@"123"];
    [arr addObject:@"2345"];
};

答案:可以犀斋,因為是addObject是使用NSMutableArray變量贝乎,而不是通過指針改變NSMutableArray,如果是arr = nil叽粹,這就是改變了NSMutableArray變量览效,會報錯蒙具。

5.1 __block的內(nèi)存管理

當(dāng)block在棧上時,并不會對__block變量產(chǎn)生強引用

Q:block的屬性修飾詞為什么是copy朽肥?

block一旦沒有進行copy操作,就不會在堆上
block在堆上持钉,程序員就可以對block做內(nèi)存管理等操作衡招,可以控制block的生命周期

Q:當(dāng)block被copy到堆時,對__block修飾的變量做了什么每强?

  • 會調(diào)用block內(nèi)部的copy函數(shù)
  • copy函數(shù)內(nèi)部會調(diào)用_Block_object_assign函數(shù)
  • _Block_object_assign函數(shù)會對__block變量形成強引用(retain)
  • 對于__block 修飾的變量 assign函數(shù)對其強引用始腾;對于外部對象 assign函數(shù)根據(jù)外部如何引用而引用
block0復(fù)制到堆上
block1復(fù)制到堆上

Q:當(dāng)block從堆中移除時,對__block修飾的變量做了什么空执?

  • 會調(diào)用block內(nèi)部的dispose函數(shù)
  • dispose函數(shù)內(nèi)部會調(diào)用_Block_object_dispose函數(shù)
  • _Block_object_dispose函數(shù)會自動釋放引用的__block變量(release)
block被廢棄
block1被廢棄

Q:block對象類型的auto變量浪箭、__block變量的區(qū)別?

從幾方面回答:

1.當(dāng)block在棧上時辨绊,對它們都不會產(chǎn)生強引用
2.當(dāng)block拷貝到堆上時
  • 都會通過copy函數(shù)來處理它們
  • 對于__block 修飾的變量 assign函數(shù)對其強引用奶栖;對于外部對象 assign函數(shù)根據(jù)外部如何引用而引用
    __block變量(假設(shè)變量名叫做a)
_Block_object_assign((void*)&dst->a, (void*)src->a, 8/*BLOCK_FIELD_IS_BYREF*/);

對象類型的auto變量(假設(shè)變量名叫做p)

_Block_object_assign((void*)&dst->p, (void*)src->p, 3/*BLOCK_FIELD_IS_OBJECT*/);

3.當(dāng)block從堆上移除時

  • 都會通過dispose函數(shù)來釋放它們
    __block變量(假設(shè)變量名叫做a)
_Block_object_dispose((void*)src->a, 8/*BLOCK_FIELD_IS_BYREF*/);

對象類型的auto變量(假設(shè)變量名叫做p)

_Block_object_dispose((void*)src->p, 3/*BLOCK_FIELD_IS_OBJECT*/);

4.__block的__forwarding指針

  • 棧上__block的__forwarding指向本身
  • 棧上__block復(fù)制到堆上后,棧上block的__forwarding指向堆上的block门坷,堆上block的__forwarding指向本身
__forwarding指向

Q:被__block修飾的對象類型在block上如何操作的宣鄙?

分幾方面回答:

1.當(dāng)__block變量在棧上時,不會對指向的對象產(chǎn)生強引用
2.當(dāng)__block變量被copy到堆時
  • 會調(diào)用__block變量內(nèi)部的copy函數(shù)
  • copy函數(shù)內(nèi)部會調(diào)用_Block_object_assign函數(shù)
  • _Block_object_assign函數(shù)會根據(jù)所指向?qū)ο蟮男揎椃╛_strong默蚌、__weak冻晤、__unsafe_unretained)做出相應(yīng)的操作,形成強引用(retain)或者弱引用(注意:這里僅限于ARC時會retain绸吸,MRC時不會retain)
  • MRC環(huán)境下不會根據(jù)對象的修飾符引用鼻弧,都是弱引用
3.如果__block變量從堆上移除
  • 會調(diào)用__block變量內(nèi)部的dispose函數(shù)
  • dispose函數(shù)內(nèi)部會調(diào)用_Block_object_dispose函數(shù)
    _Block_object_dispose函數(shù)會自動釋放指向的對象(release)

第六部分 block循環(huán)引用

Q:ARC下如何解決block循環(huán)引用的問題?

三種方式:__weak锦茁、__unsafe_unretained攘轩、__block

1.第一種方式:__weak
Person *person = [[Person alloc] init];
//        __weak Person *weakPerson = person;
__weak typeof(person) weakPerson = person;

person.block = ^{
    NSLog(@"age is %d", weakPerson.age);
};
2.第二種方式:__unsafe_unretained
__unsafe_unretained Person *person = [[Person alloc] init];
person.block = ^{
    NSLog(@"age is %d", weakPerson.age);
};
3.第三種方式:__block
__block Person *person = [[Person alloc] init];
person.block = ^{
    NSLog(@"age is %d", person.age);
    person = nil;
};
person.block();
4.三種方法比較
  • __weak:不會產(chǎn)生強引用,指向的對象銷毀時蜻势,會自動讓指針置為nil
  • __unsafe_unretained:不會產(chǎn)生強引用撑刺,不安全,指向的對象銷毀時握玛,指針存儲的地址值不變
  • __block:必須把引用對象置位nil够傍,并且要調(diào)用該block
__weak 和 __unsafe_unretained 解決循環(huán)引用方式
__block解決循環(huán)引用方式

Q:MRC下如何解決block循環(huán)引用的問題?

兩種方式:__unsafe_unretained挠铲、__block

1.第一種方式:__unsafe_unretained
__unsafe_unretained Person *person = [[Person alloc] init];
person.block = ^{
    NSLog(@"age is %d", weakPerson.age);
};
2.第二種方式:__block
__block Person *person = [[Person alloc] init];
person.block = ^{
    NSLog(@"age is %d", person.age);
};
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末冕屯,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子拂苹,更是在濱河造成了極大的恐慌安聘,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異浴韭,居然都是意外死亡丘喻,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門念颈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泉粉,“玉大人,你說我怎么就攤上這事榴芳∥嗣遥” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵窟感,是天一觀的道長讨彼。 經(jīng)常有香客問我,道長柿祈,這世上最難降的妖魔是什么哈误? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮谍夭,結(jié)果婚禮上黑滴,老公的妹妹穿的比我還像新娘。我一直安慰自己紧索,他們只是感情好袁辈,可當(dāng)我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著珠漂,像睡著了一般晚缩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上媳危,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天荞彼,我揣著相機與錄音,去河邊找鬼待笑。 笑死鸣皂,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的暮蹂。 我是一名探鬼主播寞缝,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼仰泻!你這毒婦竟也來了荆陆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤集侯,失蹤者是張志新(化名)和其女友劉穎被啼,沒想到半個月后帜消,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡浓体,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年泡挺,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片命浴。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡粘衬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出咳促,到底是詐尸還是另有隱情,我是刑警寧澤勘伺,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布跪腹,位于F島的核電站,受9級特大地震影響飞醉,放射性物質(zhì)發(fā)生泄漏冲茸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一缅帘、第九天 我趴在偏房一處隱蔽的房頂上張望轴术。 院中可真熱鬧,春花似錦钦无、人聲如沸逗栽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽彼宠。三九已至,卻和暖如春弟塞,著一層夾襖步出監(jiān)牢的瞬間凭峡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工决记, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留摧冀,地道東北人。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓系宫,卻偏偏與公主長得像索昂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子笙瑟,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,060評論 2 355

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