runloop

1.不開啟RunLoop的線程
在遇到一些耗時(shí)操作時(shí)混萝,為了避免主線程阻塞導(dǎo)致界面卡頓叠穆,影響用戶體驗(yàn)期奔,往往我們會(huì)把這些耗時(shí)操作放在一個(gè)臨時(shí)開辟的子線程中。操作完成了仿畸,子線程線性的執(zhí)行了代碼也就退出了宇色,就像下面一樣。
其中MyThread為一個(gè)重寫了dealloc的NSThread的子類
-(void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%@----開辟子線程",[NSThread currentThread]);
self.subThread = [[MyThread alloc] initWithTarget:self selector:@selector(subThreadTodo) object:nil];
self.subThread.name = @"subThread";
[self.subThread start];
// Do any additional setup after loading the view from its nib.
}
-(void)subThreadTodo
{
NSLog(@"%@----執(zhí)行子線程任務(wù)",[NSThread currentThread]);
}
{number = 1, name = main}----開辟子線程
2018-05-16 15:00:32.842971+0800 demo[4624:273971] <MyThread: 0x60000046ae00>{number = 3, name = subThread}----執(zhí)行子線程任務(wù)
2.開啟RunLoop的線程
如果這個(gè)操作需要頻繁執(zhí)行颁湖,那么按照上面那樣的邏輯宣蠕,我們就需要頻繁創(chuàng)建子線程,這是很消耗資源的甥捺。我們在設(shè)計(jì)類的時(shí)候會(huì)把需要頻繁使用的對象保持起來抢蚀,而不是頻繁創(chuàng)建一樣。我們試試把線程“保持”起來镰禾,讓它在需要的時(shí)候執(zhí)行任務(wù)皿曲。
這里沒有對線程進(jìn)行引用唱逢,也沒有讓線程內(nèi)部的任務(wù)進(jìn)行顯式的循環(huán)。為什么子線程的里面的任務(wù)沒有執(zhí)行到輸出任務(wù)結(jié)束這一步屋休,為什么子線程沒有銷毀坞古?就是因?yàn)閇runLoop run];這一行的存在。
RunLoop本質(zhì)就是個(gè)Event Loop的do while循環(huán)劫樟,所以運(yùn)行到這一行以后子線程就一直在進(jìn)行接受消息->等待->處理的循環(huán)痪枫。所以不會(huì)運(yùn)行[runLoop run];之后的代碼(這點(diǎn)需要注意,在使用RunLoop的時(shí)候如果要進(jìn)行一些數(shù)據(jù)處理之類的要放在這個(gè)函數(shù)之前否則寫的代碼不會(huì)被執(zhí)行)叠艳,也就不會(huì)因?yàn)槿蝿?wù)結(jié)束導(dǎo)致線程死亡進(jìn)而銷毀奶陈。這也就是我們最常使用RunLoop的場景之一,就如小節(jié)標(biāo)題保持線程的存活附较,而不是線性的執(zhí)行完任務(wù)就退出了吃粒。
-(void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%@----開辟子線程",[NSThread currentThread]);
self.subThread = [[MyThread alloc] initWithTarget:self selector:@selector(runloopSubThreadTodo) object:nil];
self.subThread.name = @"subThread";
[self.subThread start];
// Do any additional setup after loading the view from its nib.
}
-(void)runloopSubThreadTodo
{
NSLog(@"%@----開始執(zhí)行子線程任務(wù)",[NSThread currentThread]);
//獲取當(dāng)前子線程的RunLoop
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
//下面這一行必須加,否則RunLoop無法正常啟用拒课。我們暫時(shí)先不管這一行的意思徐勃,稍后再講。
[runLoop addPort:[NSMachPort port] forMode:NSRunLoopCommonModes];
//讓RunLoop跑起來
[runLoop run];
NSLog(@"%@----執(zhí)行子線程任務(wù)結(jié)束",[NSThread currentThread]);
}
{number = 1, name = main}----開辟子線程
2018-05-16 15:16:42.493707+0800 demo[4894:293247] <MyThread: 0x600000276ec0>{number = 3, name = subThread}----開始執(zhí)行子線程任務(wù)

RunLoop是保證線程不會(huì)退出早像,并且能在不處理消息的時(shí)候讓線程休眠疏旨,節(jié)約資源,在接收到消息的時(shí)候喚醒線程做出對應(yīng)處理的消息循環(huán)機(jī)制扎酷。它是寄生于線程的,所以提到RunLoop必然會(huì)涉及到線程遏匆。
3創(chuàng)建RunLoop
蘋果不允許直接創(chuàng)建 RunLoop法挨,它只提供了四個(gè)自動(dòng)獲取的函數(shù)
[NSRunLoop currentRunLoop];//獲取當(dāng)前線程的RunLoop
[NSRunLoop mainRunLoop];
CFRunLoopGetMain();
CFRunLoopGetCurrent();
線程和 RunLoop 之間是一一對應(yīng)的,其關(guān)系是保存在一個(gè)全局的 Dictionary 里幅聘。線程剛創(chuàng)建時(shí)并沒有 RunLoop凡纳,如果你不主動(dòng)獲取,那它一直都不會(huì)有帝蒿。RunLoop 的創(chuàng)建是發(fā)生在第一次獲取時(shí)荐糜,RunLoop 的銷毀是發(fā)生在線程結(jié)束時(shí)。你只能在一個(gè)線程的內(nèi)部獲取其 RunLoop(主線程除外)


image.png

現(xiàn)在我們結(jié)合剛才的打印結(jié)果來理解葛超。

圖中RunLoop藍(lán)色部分就對應(yīng)我們打印結(jié)果中暴氏,整個(gè)RunLoop部分的打印結(jié)果
多個(gè)綠色部分共同被包含在RunLoop內(nèi)就對應(yīng),打印結(jié)果中modes中同時(shí)包含多個(gè)Mode(這里可是看打印結(jié)果中標(biāo)注出來的第一行往上再數(shù)兩行绣张。modes = ... count = 1答渔。一個(gè)RunLoop可以包含多個(gè)Mode,每個(gè)Mode的Name不一樣侥涵,只是在這個(gè)打印結(jié)果當(dāng)中目前剛好Mode個(gè)數(shù)為1)
每一個(gè)綠色部分Mode整體就對應(yīng)沼撕,打印結(jié)果中被標(biāo)注出來的整體宋雏。
黃色部分Source對應(yīng)標(biāo)注部分source0+source1
黃色部分Observer對應(yīng)標(biāo)注部分observer部分
黃色部分Timer對應(yīng)標(biāo)注部分timers部分
RunLoop在kCFRunLoopDefaultMode下run了,但是因?yàn)樵揗ode下所有東西都為null(不包含任何內(nèi)容),所以RunLoop什么都沒做又退出來了务豺,然后線程就結(jié)束任務(wù)最后銷毀磨总。之所以要有Mode的存在是為了讓RunLoop在不同的”行為模式“之下執(zhí)行不同的”動(dòng)作“互不影響。RunLoop同一時(shí)間只能運(yùn)行在一種Mode下笼沥,當(dāng)前運(yùn)行的這個(gè)Mode叫currentMode蚪燕。
一般我們常用的Mode有三種

1.kCFRunLoopDefaultMode(CFRunLoop)/NSDefaultRunLoopMode(NSRunLoop)
默認(rèn)模式,在RunLoop沒有指定Mode的時(shí)候敬拓,默認(rèn)就跑在DefaultMode下邻薯。一般情況下App都是運(yùn)行在這個(gè)mode下的

2.(CFStringRef)UITrackingRunLoopMode(CFRunLoop)/UITrackingRunLoopMode(NSRunLoop)
一般作用于ScrollView滾動(dòng)的時(shí)候的模式,保證滑動(dòng)的時(shí)候不受其他事件影響乘凸。

3.kCFRunLoopCommonModes(CFRunLoop)/NSRunLoopCommonModes(NSRunLoop)
這個(gè)并不是某種具體的Mode厕诡,而是一種模式組合,在主線程中默認(rèn)包含了NSDefaultRunLoopMode和 UITrackingRunLoopMode营勤。子線程中只包含NSDefaultRunLoopMode灵嫌。
注意:
①在選擇RunLoop的runMode時(shí)不可以填這種模式否則會(huì)導(dǎo)致RunLoop運(yùn)行不成功。
②在添加事件源的時(shí)候填寫這個(gè)模式就相當(dāng)于向組合中所有包含的Mode中注冊了這個(gè)事件源葛作。
③你也可以通過調(diào)用CFRunLoopAddCommonMode()方法將自定義Mode放到 kCFRunLoopCommonModes組合寿羞。
source就是輸入源事件,分為source0和source1這兩種赂蠢。

1.source0:諸如UIEvent(觸摸绪穆,滑動(dòng)等),performSelector這種需要手動(dòng)觸發(fā)的操作虱岂。
2.source1:處理系統(tǒng)內(nèi)核的mach_msg事件(系統(tǒng)內(nèi)部的端口事件)玖院。諸如喚醒RunLoop或者讓RunLoop進(jìn)入休眠節(jié)省資源等。
一般來說日常開發(fā)中我們需要關(guān)注的是source0第岖,source1只需要了解难菌。
之所以說source0更重要是因?yàn)槿粘i_發(fā)中,我們需要對常駐線程進(jìn)行操作的事件大多都是source0蔑滓,稍后的實(shí)驗(yàn)會(huì)講到郊酒。
Timer即為定時(shí)源事件。通俗來講就是我們很熟悉的NSTimer键袱,其實(shí)NSTimer定時(shí)器的觸發(fā)正是基于RunLoop運(yùn)行的燎窘,所以使用NSTimer之前必須注冊到RunLoop,但是RunLoop為了節(jié)省資源并不會(huì)在非常準(zhǔn)確的時(shí)間點(diǎn)調(diào)用定時(shí)器蹄咖,如果一個(gè)任務(wù)執(zhí)行時(shí)間較長荠耽,那么當(dāng)錯(cuò)過一個(gè)時(shí)間點(diǎn)后只能等到下一個(gè)時(shí)間點(diǎn)執(zhí)行,并不會(huì)延后執(zhí)行(NSTimer提供了一個(gè)tolerance屬性用于設(shè)置寬容度比藻,如果確實(shí)想要使用NSTimer并且希望盡可能的準(zhǔn)確铝量,則可以設(shè)置此屬性)倘屹。
observer它相當(dāng)于消息循環(huán)中的一個(gè)監(jiān)聽器,隨時(shí)通知外部當(dāng)前RunLoop的運(yùn)行狀態(tài)慢叨。NSRunLoop沒有相關(guān)方法纽匙,只能通過CFRunLoop相關(guān)方法創(chuàng)建
// 創(chuàng)建observer
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
NSLog(@"----監(jiān)聽到RunLoop狀態(tài)發(fā)生改變---%zd", activity);
});
// 添加觀察者:監(jiān)聽RunLoop的狀態(tài)
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
上面的 Source/Timer/Observer 被統(tǒng)稱為 mode item,一個(gè)item可以被同時(shí)加入多個(gè)mode拍谐。但一個(gè)item被重復(fù)加入同一個(gè)mode時(shí)是不會(huì)有效果的烛缔。如果一個(gè)mode中一個(gè)item 都沒有(只有Observer也不行),則 RunLoop 會(huì)直接退出轩拨,不進(jìn)入循環(huán)践瓷。
RunLoop正常運(yùn)行的條件是:1.有Mode。2.Mode有事件源亡蓉。3.運(yùn)行在有事件源的Mode下

還有那些方法啟動(dòng)RunLoop晕翠?

NSRunLoop中總共包裝了3個(gè)方法供我們使用
1.- (void)run;
除非希望子線程永遠(yuǎn)存在,否則不建議使用砍濒,因?yàn)檫@個(gè)接口會(huì)導(dǎo)致Run Loop永久性的運(yùn)行NSDefaultRunLoopMode模式淋肾,即使使用 CFRunLoopStop(runloopRef);也無法停止RunLoop的運(yùn)行,那么這個(gè)子線程也就無法停止爸邢,只能永久運(yùn)行下去樊卓。
2.- (void)runUntilDate:(NSDate *)limitDate;
比上面的接口好點(diǎn),有個(gè)超時(shí)時(shí)間杠河,可以控制每次RunLoop的運(yùn)行時(shí)間碌尔,也是運(yùn)行在NSDefaultRunLoopMode模式。這個(gè)方法運(yùn)行RunLoop一段時(shí)間會(huì)退出給你檢查運(yùn)行條件的機(jī)會(huì)券敌,如果需要可以再次運(yùn)行RunLoop唾戚。注意CFRunLoopStop(runloopRef);仍然無法停止RunLoop的運(yùn)行,因此最好自己設(shè)置一個(gè)合理的RunLoop運(yùn)行時(shí)間陪白。比如
while (!Stop){
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]];
}
3.- (BOOL)runMode:(NSString *)mode beforeDate:(NSDate *)limitDate;
有一個(gè)超時(shí)時(shí)間限制,而且可以設(shè)置運(yùn)行模式
這個(gè)接口在非Timer事件觸發(fā)膳灶、顯式的用CFRunLoopStop停止RunLoop或者到達(dá)limitDate后會(huì)退出返回咱士。如果僅是Timer事件觸發(fā)并不會(huì)讓RunLoop退出返回,但是如果是PerfromSelector事件或者其他Input Source事件觸發(fā)處理后轧钓,RunLoop會(huì)退出返回YES序厉。同樣可以像上面那樣用while包起來使用。
結(jié)論
①.RunLoop是寄生于線程的消息循環(huán)機(jī)制毕箍,它能保證線程存活弛房,而不是線性執(zhí)行完任務(wù)就消亡。

②.RunLoop與線程是一一對應(yīng)的而柑,每個(gè)線程只有唯一與之對應(yīng)的一個(gè)RunLoop文捶。我們不能創(chuàng)建RunLoop荷逞,只能在當(dāng)前線程當(dāng)中獲取線程對應(yīng)的RunLoop(主線程RunLoop除外)。

③.子線程默認(rèn)沒有RunLoop粹排,需要我們?nèi)ブ鲃?dòng)開啟种远,但是主線程是自動(dòng)開啟了RunLoop的。

④.RunLoop想要正常啟用需要運(yùn)行在添加了事件源的Mode下顽耳。

⑤.RunLoop有三種啟動(dòng)方式run坠敷、runUntilDate:(NSDate *)limitDate、runMode:(NSString *)mode beforeDate:(NSDate *)limitDate射富。第一種無條件永遠(yuǎn)運(yùn)行RunLoop并且無法停止膝迎,線程永遠(yuǎn)存在。第二種會(huì)在時(shí)間到后退出RunLoop胰耗,同樣無法主動(dòng)停止RunLoop限次。前兩種都是在NSDefaultRunLoopMode模式下運(yùn)行吨拍。第三種可以選定運(yùn)行模式尤莺,并且在時(shí)間到后或者觸發(fā)了非Timer的事件后退出佩迟。

3 要把Timer加到一個(gè)叫RunLoop的東西里面才能正常運(yùn)行

  • (void)viewDidLoad {
    [super viewDidLoad];

    NSTimer *timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(wantTodo) userInfo:nil repeats:YES];
    //timerWith開頭的方法創(chuàng)建的Timer如果不加下面一句無法運(yùn)行娃善。
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    }
    注意:GCD的timer與NStimer不是一個(gè)東西吟税。他倆中只有NSTimer是與RunLoop相關(guān)的
    scheduedTimerWith開頭的方法創(chuàng)建的NSTimer就不需要添加到RunLoop中就可以運(yùn)行振劳。事實(shí)上署驻,這一系列方法的真實(shí)邏輯是驾霜,創(chuàng)建一個(gè)定時(shí)器并自動(dòng)添加到當(dāng)前線程RunLoop的NSDefaultRunLoopMode中乎串。在聲明一次店枣,不添加到RunLoop中的NSTimer是無法正常工作的

  • (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
  • (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo
  • (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block ;//iOS10以后新加的方法
  • (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
  • (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo
  • (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block ;//iOS10以后新加的方法
    在進(jìn)行Scrollview的滾動(dòng)操作時(shí)Timer不進(jìn)行響應(yīng),滑動(dòng)結(jié)束后timer又恢復(fù)正常了√居現(xiàn)在對RunLoop有一定了解了鸯两,我們不妨來分析一下以便加深理解。

1)在之前講Mode的時(shí)候提到過长豁,RunLoop每次只能運(yùn)行在一個(gè)Mode下钧唐,其意義是讓不同Mode中的item互不影響。
2)NSTimer是一個(gè)Timer源(item)匠襟,在上面哪個(gè)例子中不管是[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];還是scheduedTimerWith我們都是把Timer加到了主線程RunLoop的NSDefaultRunLoopMode中钝侠。一般情況下主線程RunLoop就運(yùn)行在NSDefaultRunLoopMode下,所以定時(shí)器正常運(yùn)行酸舍。
3)當(dāng)Scrollview開始滑動(dòng)時(shí)帅韧,主線程RunLoop自動(dòng)切換了當(dāng)前運(yùn)行的Mode(currentMode),變成了UITrackingRunLoopMode啃勉。所以現(xiàn)在RunLoop要處理的就是UITrackingRunLoopMode中item忽舟。
4)我們的timer是添加在NSDefaultRunLoopMode中的,并沒有添加到UITrackingRunLoopMode中。即我們的timer不是UITrackingRunLoopMode中的item叮阅。
5)本著不同Mode中的item互不影響的原則刁品,RunLoop也就不會(huì)處理非當(dāng)前Mode的item,所以定時(shí)器就不會(huì)響應(yīng)。
6)當(dāng)Scrollview滑動(dòng)結(jié)束帘饶,主線程RunLoop自動(dòng)切換了當(dāng)前運(yùn)行的Mode(currentMode)哑诊,變成了NSDefaultRunLoopMode。我們的Timer是NSDefaultRunLoopMode的item及刻,所以RunLoop會(huì)處理它镀裤,所以又正常響應(yīng)了。
如果想Timer在兩種Mode中都得到響應(yīng)怎么辦缴饭?前面提到過暑劝,一個(gè)item可以被同時(shí)加入多個(gè)mode。讓Timer同時(shí)成為兩種Mode的item就可以了(分別添加或者直接加到commonMode中)颗搂,這樣不管RunLoop處于什么Mode担猛,timer都是當(dāng)前Mode的item,都會(huì)得到處理丢氢。

當(dāng)tableview的cell上有需要從網(wǎng)絡(luò)獲取的圖片的時(shí)候傅联,異步線程會(huì)去加載圖片,加載完成后主線程就會(huì)設(shè)置cell的圖片疚察,有可能會(huì)造成卡頓蒸走。可以讓設(shè)置圖片的任務(wù)在CFRunLoopDefaultMode下進(jìn)行貌嫡,當(dāng)滾動(dòng)tableView的時(shí)候比驻,RunLoop是在 UITrackingRunLoopMode 下進(jìn)行,不去設(shè)置圖片岛抄,而是當(dāng)停止的時(shí)候别惦,再去設(shè)置圖片。(這個(gè)場景的核心還是利用不同Mode的切換的思想夫椭,可以拓展其他地方)
[self.myImageView performSelector:@selector(setImage:)
withObject:[UIImage imageNamed:@""]
afterDelay:0
inModes:@[NSDefaultRunLoopMode]];
當(dāng)然不是說這種方法就一定好掸掸,畢竟他在滑動(dòng)的時(shí)候不會(huì)顯示圖片,萬一你的需求跟這剛好相反呢蹭秋,而且現(xiàn)在SDWebImage處理的已經(jīng)很好了扰付,已經(jīng)很少有人用這種方法了。但是這個(gè)利用Mode切換的思想可以借鑒感凤,萬一其他地方用上就很合適呢悯周。

4.Timer和Source以及一些回調(diào)block等等粒督,都需要占用一部分存儲(chǔ)空間陪竿,所以要釋放掉,如果不釋放掉,就會(huì)一直積累族跛,占用的內(nèi)存也就越來越大闰挡。

在主線程中

當(dāng)RunLoop開啟時(shí),會(huì)自動(dòng)創(chuàng)建一個(gè)自動(dòng)釋放池礁哄。
當(dāng)RunLoop在休息之前會(huì)釋放掉自動(dòng)釋放池的東西长酗。
然后重新創(chuàng)建一個(gè)新的空的自動(dòng)釋放池。
當(dāng)RunLoop被喚醒重新開始跑圈時(shí)桐绒,Timer,Source等新的事件就會(huì)放到新的自動(dòng)釋放池中夺脾。
重復(fù)2-4。
所以主線程中茉继,有關(guān)RunLoop的釋放問題不需要我們關(guān)心咧叭。

注意:這里說的是主線程(關(guān)于子線程的autoreleasepool是否需要手動(dòng)創(chuàng)建還有個(gè)研究過程,因?yàn)榫W(wǎng)上眾說紛紜烁竭,有的說不需要?jiǎng)?chuàng)建有的說需要菲茬。)這部分的資料也比較少,總結(jié)了有限的資料加上自己的一些理解我認(rèn)為RunLoop正確的寫法
1)需要用while循環(huán)控制的RunLoop
@autoreleasepool {
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
while (!self.isNeedStopRunLoop) {
//這里RunLoop不需要添加autoreleasepool
//每個(gè)RunLoop內(nèi)部都會(huì)自動(dòng)管理autoreleasepool
//事件源等一些autorelease對象會(huì)在RunLoop的迭代中自動(dòng)釋放派撕。
[runLoop runMode:NSDefaultRunLoopMode
beforeDate:[NSDate distantFuture]];
//[runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]];
}
2) 不需要用while循環(huán)控制的RunLoop
@autoreleasepool {
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
[runLoop run];
//[runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]];
}
http://www.cocoachina.com/ios/20180515/23380.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末婉弹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子终吼,更是在濱河造成了極大的恐慌镀赌,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件衔峰,死亡現(xiàn)場離奇詭異佩脊,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)垫卤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門威彰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人穴肘,你說我怎么就攤上這事歇盼。” “怎么了评抚?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵豹缀,是天一觀的道長。 經(jīng)常有香客問我慨代,道長邢笙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任侍匙,我火速辦了婚禮氮惯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己妇汗,他們只是感情好帘不,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著杨箭,像睡著了一般寞焙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上互婿,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天捣郊,我揣著相機(jī)與錄音,去河邊找鬼慈参。 笑死模她,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的懂牧。 我是一名探鬼主播侈净,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼僧凤!你這毒婦竟也來了畜侦?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤躯保,失蹤者是張志新(化名)和其女友劉穎旋膳,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體途事,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡验懊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了尸变。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片义图。...
    茶點(diǎn)故事閱讀 40,488評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖召烂,靈堂內(nèi)的尸體忽然破棺而出碱工,到底是詐尸還是另有隱情,我是刑警寧澤奏夫,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布怕篷,位于F島的核電站,受9級特大地震影響酗昼,放射性物質(zhì)發(fā)生泄漏廊谓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一麻削、第九天 我趴在偏房一處隱蔽的房頂上張望蒸痹。 院中可真熱鬧舔示,春花似錦、人聲如沸电抚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蝙叛。三九已至,卻和暖如春公给,著一層夾襖步出監(jiān)牢的瞬間借帘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工淌铐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留肺然,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓腿准,卻偏偏與公主長得像际起,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子吐葱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評論 2 359

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