定時器

  • 定時器的的概念

一個在確定時間間隔內(nèi)執(zhí)行一個或者多個我們制定對象的方法的對象
先拋出一個問題溜徙,如果多次執(zhí)行對象的方法,它怎么保證執(zhí)行的是否對象不被釋放呢
先給出幾個問題

1.你知道NSTimer會retain你添加調(diào)用方法的對象嗎
2.你知道NSTimer并不是每次都準(zhǔn)備的按照你設(shè)定的時間來執(zhí)行嗎
3.NSTimer需要和NSRunloop結(jié)合起來使用,你知道需要怎么結(jié)合使用嗎
4.除了NSTimer,還有哪幾種定時器嗎

帶著問題開始上代碼測試

  • 定時器的引用場景

應(yīng)用場景自然不用說冤荆,太多了,購物的限時搶購权纤,尋車?yán)锏牡褂嫊r等等

  • 定時器的常用方式

-(void)startTimerOne{

    _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
}

-(void)startTimerTwo{

    _timer= [NSTimer timerWithTimeInterval:1.f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
}

-(void)timerAction{

    NSLog(@"timerAction");
}

如上兩個開啟定時器的方式钓简,分別調(diào)用測試,發(fā)現(xiàn)startTimerOne會開啟定時會有打印汹想,而startTimerTwo沒有打印
好的外邓,那么這兩個方法有什么區(qū)別,按住option鍵查看下官方怎么說的

E92826F4-2F84-4D5F-8B4B-5D30213F13A5.png
D1FD62EE-C3D7-414D-BADB-490409D06A5F.png

文檔上介紹的這兩種方法的區(qū)別
scheduledTimerWithTimeInterval:創(chuàng)建并且返回一個NSTimer對象古掏,并且把這個對象提交到當(dāng)前的runloop上以默認(rèn)的runloop模式

timerWithTimeInterval:創(chuàng)建并且返回一個NSTimer的對象损话,你自己必須把這個新創(chuàng)建的timer對象加入到runloop中,用addTimer:forMode:方法槽唾,在一個周期之后開始觸發(fā)你設(shè)定的方法(這是什么意思呢)

_timer= [NSTimer timerWithTimeInterval:5.f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];

比如創(chuàng)建了timer丧枪,也添加了到runloop中,但是它不會馬上執(zhí)行庞萍,而是會等一個周期拧烦,這里的周期是5秒,那么如果想從當(dāng)前時間馬上開始钝计,就得

 _timer= [NSTimer timerWithTimeInterval:5.f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
 [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];
 [_timer fire];//添加個方法
  • fire方法的正確理解

上面提到了這個方法恋博,這個方法用來干什么的呢:使接收方的消息被發(fā)送到其目標(biāo)。
您可以使用此方法觸發(fā)重復(fù)計時器私恬,而不中斷其常規(guī)觸發(fā)調(diào)度周期债沮。如果計時器不重復(fù),則在fire自動失效践付,即使它的預(yù)定fire日期還沒有到達(dá)秦士。

  • NSRunloopMode對定時器的影響

如果你的定時器的mode是NSDefaultRunLoopMode ,那么滑動UIScrollView的話永高,那么定時器就會停止
因為runloop同一時間只會處理一種mode隧土,而UIScrollView滑動是trackingMode提针,而trackingMode比NSDefaultRunLoopMode的優(yōu)先級要高,而另一種NSRunloopCommonModes包含了這兩種mode曹傀,所以只要把定時器的mode設(shè)置成這個就解決了UIScrollView滑動的問題
如果把定時器加入到trackingMode模式的話會怎么樣呢辐脖,就是有滑動UI的時候,定時器打印就在皆愉,滑動停止嗜价,打印沒了,因為UI模式只能被UI事件喚醒

如果把定時器加入到NSRunloopCommonModes模式其實就是這兩句話代碼

 [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
  • 定時器一定會在規(guī)定時間間隔內(nèi)事實觸發(fā)事件嗎

- (void)viewDidLoad {
    [super viewDidLoad];
  
    [self startTimerTwo];

 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
        [self doBusyThings];
    });
    
}

-(void)doBusyThings{

    NSUInteger count = 0xFFFFFFF;
    CGFloat num =0.f;
    for (int i =0; i<count; i++) {
        num=i/count;
    }
}

-(void)startTimerTwo{

    _timer= [NSTimer timerWithTimeInterval:1.f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
    [_timer fire];
}

代碼意思是在執(zhí)行定時器三秒給一個耗時操作

C1801049-1C1C-4BCA-88A5-519A25461ABF.png

有個耗時的操作幕庐,所以導(dǎo)致了定時器沒有按周期規(guī)律性的在進(jìn)行
所以久锥,在定時器的線程里不應(yīng)該有太耗時的操作

定時器的任務(wù)里也不應(yīng)該有耗時操作,一定有耗時操作异剥,建議在子線程里做

  • 定時器引起的循環(huán)引用

我們新建一個控制器TestViewController瑟由,點擊ViewController里的listTableView跳轉(zhuǎn)到TestViewController,在這里開啟一個定時器,并且在delloc里invalidate定時器

- (void)viewDidLoad {
    [super viewDidLoad];

    [self startTimerOne];
}

-(void)dealloc{
    [_timer invalidate];
    NSLog(@"dealloc:%s",__func__);
}

- (IBAction)goBack:(UIButton *)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}

-(void)timerAction{
  
    NSLog(@"timerAction");
}


-(void)startTimerOne{
    
    _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
}

然后點擊返回到上一個界面發(fā)現(xiàn)定時器仍然在進(jìn)行冤寿,并且沒有進(jìn)入delloc方法歹苦,說明TestViewController控制器也沒有銷毀

DE7AAB31-A98F-4538-B68C-86D90CC58668.png

看圈起的這段解釋:該對象發(fā)送消息時指定的aSeltetor定時器。定時器保持對目標(biāo)的強引用督怜,直到定時器(定時器)失效為止
簡單的說:_timer 定時器會對self進(jìn)行強引用殴瘦,知道定時器銷毀
而現(xiàn)在的引用關(guān)系為:
self->_timer :self強引用_timer
_timer->self:_timer又強引用了self
而_timer的銷毀又依賴于delloc方法里的[_timer invalidate];
但是self的銷毀又依賴于_timer的銷毀,也就是如果_timer不銷毀号杠,又不會跑入delloc蚪腋,所以形成了循環(huán)引用

其實這種問題的解決方法大家都知道,但是我們先不直接說怎么解決究流,我們多做幾種假設(shè)

假設(shè)1:既然知道_timer對于self有了強引用辣吃,那我們參數(shù)block的方法,那我們能不能把self改成weakself芬探,那么就不是強引用了呢神得,代碼上來

-(void)startTimerOne{
    
    __weak typeof(self)weakSelf=self;
    _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:weakSelf selector:@selector(timerAction) userInfo:nil repeats:YES];
}

測試結(jié)果:然后點擊返回到上一個界面發(fā)現(xiàn)定時器仍然在進(jìn)行,并且沒有進(jìn)入delloc方法偷仿,說明TestViewController控制器也沒有銷毀
為什么會這樣呢哩簿,不是說好的弱引用嗎,原因是這樣的:牽扯到內(nèi)存酝静,self就是個指針节榜,它指向viewcontroller,引用計數(shù)加1别智,為weakself也指向viewcontroller宗苍,它只是弱引用,計數(shù)不加1,但是_timer對weakself強引用了讳窟,因為為weakself也指向viewcontroller让歼,所以_timer對viewcontroller也計數(shù)加1了,也就說強引用一個弱引用也是強引用丽啡,那很多人說為什么block只需要weakself就行了谋右,那是因為如果用self,那么block就強引用self补箍,如果用weak self那么就弱引用self改执,但是如上圖黑色圈出的部分所說,不管你是強還是弱坑雅,跟我沒關(guān)系辈挂,我都會強引用你

假設(shè)2:既然weakself不行,那我把_timer設(shè)置成__weak呢

@interface TestViewController ()

@property(nonatomic,weak)NSTimer * timer;

@end

-(void)startTimerTwo{
    
    _timer= [NSTimer timerWithTimeInterval:1.f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];
    [_timer fire];
}

這樣肯定不行嘛

345F674C-F24F-4294-84BD-4455579E1FEB.png

因為_timer在創(chuàng)建后就釋放了為nil霞丧,你要添加一個已經(jīng)釋放的內(nèi)存nil就是奔潰

假設(shè)3:換一種創(chuàng)建timer的方法,這先說明下結(jié)果呢岗,單純了換種方式,只是不會奔潰蛹尝,但是返回上一控制器的時候,定時器還是跑悉尾,那么干脆就說下循環(huán)引用的解決方式突那,不是self -> _timer 并且 _timer->self嗎,好了构眯,那我們在viewWillDisappear把定時器銷毀不就好了嘛愕难,這就是答案

@interface TestViewController ()

@property(nonatomic,weak)NSTimer * timer;

@end

@implementation TestViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self startTimerOne];
}

-(void)viewWillDisappear:(BOOL)animated{

    [super viewWillDisappear:animated];
    [_timer invalidate];
    _timer=nil;
}

-(void)dealloc{
    [_timer invalidate];
    NSLog(@"dealloc:%s",__func__);
}

- (IBAction)goBack:(UIButton *)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}

-(void)timerAction{
  
    
    NSLog(@"timerAction");
}


-(void)startTimerOne{
    
    //__weak typeof(self)weakSelf=self;
    _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
}

-(void)startTimerTwo{
    
    _timer= [NSTimer timerWithTimeInterval:1.f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];
    [_timer fire];
}


@end

好了,循環(huán)引用的問題是解決了惫霸,但是大家發(fā)現(xiàn)一個問題了猫缭,_timer是weak的,應(yīng)該創(chuàng)建后就釋放了啊,按理來說在viewWillDisappear使用_timer是不能夠銷毀定時器吧壹店,但是這為什么又能用了猜丹,這是因為scheduledTimerWithTimeInterval 在創(chuàng)建定時器的時候順便把定時器加在了當(dāng)前的runloop 里,runloop對_timer進(jìn)行了強引用硅卢,那么此時的引用關(guān)系:
1.runloop->_timer->self
2.self->timer;
所以關(guān)鍵一步就是_timer 要invalidate射窒,如果把_timer給invalidate,那么就相當(dāng)于把_timer從runloop 中移除了将塑,這就把1的線給斷了是不是脉顿,如果timer是weak型那么這時timer就為nil,如果timer是strong型的点寥,隨著控制器的釋放它也就被釋放晾咪,所以在這種創(chuàng)建定時器的方式無論weak和strong并不影響定時器的運行

好了,解決第一種方式為

-(void)viewWillDisappear:(BOOL)animated{

    [super viewWillDisappear:animated];
    [_timer invalidate];
    _timer=nil;
}

那么我可以考慮下岔绸, 在timer上動手腳好像是不行的,無論怎么變都行不通了對吧误褪,換個角度不老說self的強引用嗎,如果我們創(chuàng)建的時候不引入當(dāng)前控制器的對象會怎么樣呢
建一個NSTimer 的分類

@interface NSTimer (EYTimer)

+(instancetype)ey_timerWithTimeInterval:(NSInteger)ti block:(void(^)(void))block repeated:(BOOL)repeat;
@end

+(instancetype)ey_timerWithTimeInterval:(NSInteger)ti block:(void(^)(void))block repeated:(BOOL)repeat{

    NSTimer * timer = [NSTimer timerWithTimeInterval:ti target:self selector:@selector(handleTimerAction:) userInfo:block repeats:repeat];
    return timer;
}

+(void)handleTimerAction:(NSTimer*)timer{

    void(^block)()=timer.userInfo;
    if (block) {
        block();
    }
    
}

@end

調(diào)用

@interface TestViewController ()

@property(nonatomic,strong)NSTimer * timer;

@end

@implementation TestViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self ey_startTimer];
}

-(void)ey_startTimer{

    __weak typeof(self)weakSelf=self;
    _timer = [NSTimer ey_timerWithTimeInterval:1.0 block:^{
        [weakSelf timerAction];
        
    } repeated:YES];
    [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];
}


-(void)dealloc{
    NSLog(@"dealloc:%s",__func__);
}
//
- (IBAction)goBack:(UIButton *)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}

-(void)timerAction{
  
    
    NSLog(@"timerAction");
}

先簡單介紹下上面代碼的block:
block在arc的模式下碾褂,一般情況下兽间,它自動copy的,就是從棧block copy到堆block上正塌,作為property,用copy/strong都是一樣的
作為自己函數(shù)的參數(shù)嘀略,block一般是不copy的,系統(tǒng)的一些哪怕是函數(shù)參數(shù)也會copy
可能蘋果開發(fā)知道這個循環(huán)引用不好乓诽,然后在iOS 10以后是有這種API的

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
  • 子線程開啟定時器

- (void)viewDidLoad {
    [super viewDidLoad];
    [NSThread detachNewThreadSelector:@selector(threadTimer) toTarget:self withObject:nil];
    
}

-(void)threadTimer{
    
    NSLog(@"%@",[NSThread currentThread]);
    _timer= [NSTimer timerWithTimeInterval:1.f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];
}

開啟一個字線程帜羊,在字線程里開啟定時器,發(fā)現(xiàn)沒有打印log鸠天,說明了定時器并沒有運行,因為什么呢讼育,因為在字線程的里runloop需要手動開啟,主線程系統(tǒng)幫你開啟了

-(void)threadTimer{
    
    NSLog(@"%@",[NSThread currentThread]);
    _timer= [NSTimer timerWithTimeInterval:1.f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] run];//開啟runloop
NSLog(@"字線程沒了");
}

開啟runloop就行稠集,這里也介紹下runloop的創(chuàng)建奶段,并不能用alloc,其實[NSRunLoop currentRunLoop] 就先相當(dāng)于有就獲取沒有就創(chuàng)建剥纷,類似于懶加載的意思
那么怎么取消字線程的定時器呢

-(void)timerInvalidate{

    [_timer invalidate];

    _timer =nil;
}

給一個點擊方法調(diào)用timerInvalidate痹籍,測試結(jié)果就是在定時器運行的時候點擊下,結(jié)果定時器沒有相應(yīng)了晦鞋,那么字線程的定時器在主線程上取消到底行不行?答案應(yīng)該是不行的蹲缠,應(yīng)該在字線程的runloopshang添加一個timer,當(dāng)timer資源失效的時候悠垛,runloop也應(yīng)該失效了线定,死循環(huán)也應(yīng)該沒了

NSLog(@"字線程沒了");

這句代碼應(yīng)該打印出來才對,但是經(jīng)過測試這句并沒有打印
這說明了字線程的定時器就應(yīng)該在字線程上干掉它确买,不要在主線程上invalidate斤讥,否則會造成runloop資源的浪費
所以開啟字線程定時器的代碼如下

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self listTableView];
    
    //[self startTimerOne];
    //[self startTimerTwo];
    
    [NSThread detachNewThreadSelector:@selector(threadTimer) toTarget:self withObject:nil];
    
    
}

-(void)threadTimer{
    
    NSLog(@"%@",[NSThread currentThread]);
    _timer= [NSTimer timerWithTimeInterval:1.f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];
    //[[NSRunLoop currentRunLoop] run];
   // [[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    /*
     運行runloop的幾種方式
     1.- (void)run; 
     無條件運行
     因為這個接口會導(dǎo)致runloop永久性的運行在NSDefaultRunLoopMode模式,沒有超時機制
     即使使用CFRunLoopStop(runloopRef);也無法停止Run Loop的運行拇惋,那么這個子線程就無法停止周偎,只能永久運行下去。
     
     2.- (BOOL)runMode:(NSString *)mode beforeDate:(NSDate *)limitDate;
     參數(shù)為運行模式撑帖、時間期限
     即使limitDate的初始值小于當(dāng)前的Date蓉坎,RunLoop也會執(zhí)行一次然后馬上返回YES
     
     3.- (void)runUntilDate:(NSDate *)limitDate;
     參數(shù)為時間期限,運行模式為默認(rèn)的NSDefaultRunLoopMode模式
     無法使用CFRunLoopStop(runLoopRef)來停止RunLoop的運行
     
     總結(jié):建議是使用第二個接口來運行,因為它能夠設(shè)置Run Loop的運行參數(shù)最多胡嘿,而且最重要的是可以使用CFRunLoopStop(runLoopRef)來停止Run Loop的運行蛉艾,而第一個和第三個接口無法使用CFRunLoopStop(runLoopRef)來停止Run Loop的運行
     */
    NSLog(@"字線程沒了");
}

-(void)timerAction{
    
    static int i=0;
    i++;
    if (i==5) {
        CFRunLoopStop([NSRunLoop currentRunLoop].getCFRunLoop);
    }
    NSLog(@"timerAction");
}

經(jīng)過測試,@"字線程沒了"被打印出來了

  • GCD定時器

GCD定時器跟應(yīng)該是內(nèi)置了runloop,

- (void)viewDidLoad {
    [super viewDidLoad];

    //[self startTimerOne];
    //[self ey_startTimer];
    [self gcdTimer:1 repeat:YES];
}

-(void)gcdTimer:(NSTimeInterval)timeInter repeat:(BOOL)repeat{

    dispatch_queue_t queue = dispatch_queue_create("edison", 0);
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, timeInter * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(timer, ^{
        
        [self timerAction];
    });
    dispatch_resume(timer);
}

可是為什么定時器沒起來呢勿侯,為什么呢拓瞪,
修改下代碼:dispatch_source_t timer設(shè)置成員變量
結(jié)果就可以運行定時器了,原因在于如果是局部變量執(zhí)行一次后對象就釋放了助琐,沒有被持有
再修改下代碼,還是設(shè)置成局部變量祭埂,只是在dispatch_source_set_event_handler里寫一次timer


-(void)gcdTimer:(NSTimeInterval)timeInter repeat:(BOOL)repeat{

    dispatch_queue_t queue = dispatch_queue_create("edison", 0);
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, timeInter * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(timer, ^{
        
        timer;
        [self timerAction];
    });
    dispatch_resume(timer);
}

這又是為什么n:內(nèi)存問題,
dispatch_source_set_event_handler沒有包含timer:當(dāng)前timer為成員變量的時候沒有問題兵钮,當(dāng)為局部變量的時候只運行了一次
dispatch_source_set_event_handler包含timer:為局部變量的時候蛆橡,因為block會對timer引用計數(shù)加1,所以不會被釋放掉

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末掘譬,一起剝皮案震驚了整個濱河市泰演,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌葱轩,老刑警劉巖睦焕,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異靴拱,居然都是意外死亡垃喊,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門缭嫡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缔御,“玉大人,你說我怎么就攤上這事妇蛀。” “怎么了笤成?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵评架,是天一觀的道長。 經(jīng)常有香客問我炕泳,道長纵诞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任培遵,我火速辦了婚禮浙芙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘籽腕。我一直安慰自己嗡呼,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布皇耗。 她就那樣靜靜地躺著南窗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上万伤,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天窒悔,我揣著相機與錄音,去河邊找鬼敌买。 笑死简珠,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的虹钮。 我是一名探鬼主播聋庵,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼芜抒!你這毒婦竟也來了珍策?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤宅倒,失蹤者是張志新(化名)和其女友劉穎攘宙,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拐迁,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡蹭劈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了线召。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铺韧。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖缓淹,靈堂內(nèi)的尸體忽然破棺而出哈打,到底是詐尸還是另有隱情,我是刑警寧澤讯壶,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布料仗,位于F島的核電站,受9級特大地震影響伏蚊,放射性物質(zhì)發(fā)生泄漏立轧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一躏吊、第九天 我趴在偏房一處隱蔽的房頂上張望氛改。 院中可真熱鬧,春花似錦比伏、人聲如沸胜卤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瑰艘。三九已至是鬼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間紫新,已是汗流浹背均蜜。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留芒率,地道東北人囤耳。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像偶芍,于是被迫代替她去往敵國和親充择。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

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