iOS開發(fā)之runloop

runLoop,正如其名插佛,表示一直運(yùn)行著的循環(huán)杠巡。

一般來說,一個(gè)線程只能執(zhí)行一個(gè)任務(wù)雇寇,執(zhí)行完就會(huì)推出氢拥,如果我們需要一種機(jī)制,讓線程能隨時(shí)處理時(shí)間但并不退出锨侯,而runLoop就是這樣一個(gè)機(jī)制嫩海;而這種機(jī)制的關(guān)鍵在于:如何管理消息/消息,如何讓線程在沒有處理消息的時(shí)候休眠以避免資源占用识腿,在有消息的時(shí)刻立刻被喚醒出革。

所以,runLoop實(shí)際上就是一個(gè)對(duì)象渡讼,這個(gè)對(duì)象管理了其需要處理的時(shí)間和消息,并提供了一個(gè)入口函數(shù)來執(zhí)行上面的邏輯骂束。線程執(zhí)行了這個(gè)函數(shù)之后耳璧,就會(huì)一直處于“接收消息-等待-處理”的循環(huán)中,知道這個(gè)循環(huán)結(jié)束展箱,函數(shù)返回旨枯。

ios提供了兩個(gè)這樣的對(duì)象:NSRunLoop和CFRunLoopRef。

一混驰、線程與runLoop

1.線程任務(wù)的類型

① 直線線程:該線程執(zhí)行的任務(wù)是一條直線攀隔;

② 圓形線程:該線程是一個(gè)圓,不斷循環(huán)栖榨,知道通過某種方式截止昆汹,ios中,圓形線程就是通過runLoop實(shí)現(xiàn)的婴栽。

2.線程與runLoop的關(guān)系

① runLoop和線程緊密相連满粗,可以說,runLoop是為了線程而生的,沒有線程,就沒有runLoop存在的必要愚争;

② 每個(gè)線程都有其對(duì)應(yīng)的runLoop對(duì)象映皆;

③ 主線程的runLoop是默認(rèn)啟動(dòng)的,而其他線程的runLoop是默認(rèn)沒有啟動(dòng)的轰枝;

二捅彻、RunLoop輸入事件來源

runLoop接收的輸入事件來自兩種來源:輸入源和定時(shí)源;

1.輸入源

傳遞異步事件鞍陨,通常消息來自其他線程或程序步淹。輸入源傳遞異步消息給相應(yīng)的處理程序,并調(diào)用runUntilDate方法來退出诚撵;

當(dāng)你創(chuàng)建輸入源贤旷,需要將其分配給runLoop的一個(gè)或多個(gè)模式,模式只會(huì)在特定事件影響監(jiān)聽的源砾脑。

以下是輸入源的類型:

① 基于端口的輸入源:基于端口的輸入源是有內(nèi)核自動(dòng)發(fā)送;

cocoa和Core Foundation內(nèi)置支持使用端口相關(guān)的對(duì)象和函數(shù)來創(chuàng)建基于端口的源艾杏。

例如:在Core Foundation中韧衣,使用端口相關(guān)的函數(shù)來創(chuàng)建端口和runLoop源;

② 自定義輸入源:自定義源需要人工從其他線程發(fā)送购桑。

Core Foundation中可以使用CFRunLoopSourceRef等來創(chuàng)建源畅铭,也可以使用回調(diào)函數(shù)來配置源。Core Foundation會(huì)在配置源的不同地方調(diào)用回調(diào)函數(shù)勃蜘,處理輸入事件硕噩,在源從runLoop移除的時(shí)候清理它;

③ Cocoa上的selector源

2.定時(shí)源

定時(shí)源在預(yù)設(shè)的時(shí)間點(diǎn)同步傳遞消息缭贡,這些消息都會(huì)在特定事件或者重復(fù)的時(shí)間間隔炉擅,定時(shí)源則傳遞消息個(gè)處理線程辉懒,不會(huì)立即退出runLoop。

定時(shí)器并不是實(shí)時(shí)機(jī)制谍失,定時(shí)器和你的runLoop的特定模式相關(guān)眶俩,如果定時(shí)器所在的模式當(dāng)前未被runLoop監(jiān)視,那么定時(shí)器將不會(huì)開始快鱼,知道runLoop運(yùn)行在響應(yīng)的模式下颠印。

三、RunLoop的相關(guān)知識(shí)點(diǎn)

1.runLoop的模式

runLoop中使用mode來指定時(shí)間在運(yùn)行循環(huán)中的優(yōu)先級(jí)抹竹,分為:

① NSDefaultRunLoopMode(kCFRunLoopDefaultMode): 默認(rèn)线罕,空閑狀態(tài);

② UITrackingRunLoopMode:scrollView滑動(dòng)時(shí)窃判;

③ UIInitializationRunLoopMode: 啟動(dòng)時(shí)钞楼;

④ NSRunLoopCommonModes(kCFRunLoopCommonModes):mode集合。

ps:其中①和④是蘋果公開的mode兢孝。

2.runLoop觀察者

源是在合適的同步或異步事件發(fā)生時(shí)觸發(fā)窿凤,而runLoop觀察者則是在runLoop本身運(yùn)行的特定時(shí)候觸發(fā),你可以使用runLoop觀察者為處理某一特定事件或是進(jìn)入休眠的程序做準(zhǔn)備跨蟹■ㄊ猓可以將runLoop觀察者和以下事件關(guān)聯(lián):

① runLoop入口

② runLoop何時(shí)處理一個(gè)定時(shí)器;

③ runLoop何時(shí)處理一個(gè)輸入源窗轩;

④ runLoop何時(shí)進(jìn)入睡眠狀態(tài)夯秃;

⑤ runLoop何時(shí)被喚醒,但在喚醒之前要處理的事件痢艺;

⑥ runLoop終止仓洼;

在創(chuàng)建的時(shí)候,也可以指定runLoop觀察者可以只用一次或者循環(huán)使用堤舒,若只用一次色建,那么它在啟動(dòng)后,會(huì)把自己從runLoop中移除舌缤,而循環(huán)的觀察者不會(huì)箕戳。

3.runLoop事件隊(duì)列

每次運(yùn)行runLoop,線程的runLoop會(huì)自動(dòng)處理之前未處理的消息国撵,并通知相關(guān)的觀察者陵吸,具體的順序如下:

① 通知觀察者runLoop已經(jīng)啟動(dòng);

② 通知觀察者任何即將要開始的定時(shí)器介牙;

③ 通知觀察著任何即將啟動(dòng)的非基于端口的源壮虫;

④ 啟動(dòng)任何準(zhǔn)備好的非基于端口的源;

⑤ 如果基于端口的源準(zhǔn)備好并處于等待狀態(tài)环础,立即啟動(dòng)囚似,并進(jìn)入步驟⑨剩拢;

⑥ 通著觀察者線程進(jìn)入休眠;

⑦ 將線程至于休眠知道任意下面的事件發(fā)生:

A.某一時(shí)間到達(dá)基于端口的源谆构;

B.定時(shí)器啟動(dòng)裸扶;

C.runLoop設(shè)置的時(shí)間已經(jīng)超過;

D.runLoop被顯示喚醒搬素;

⑧ 通知觀察者線程將被喚醒呵晨;

⑨ 處理未處理的事件

A.如果用戶定義的定時(shí)器啟動(dòng),處理定時(shí)器并重啟runLoop熬尺,進(jìn)入步驟2

B.如果輸入源啟動(dòng)摸屠,傳遞響應(yīng)的消息;

C.如果runLoop被顯示喚醒粱哼,而且時(shí)間還沒超過季二,重啟runLoop,進(jìn)入步驟2

⑩ 通知觀察者runLoop結(jié)束揭措。

ps:

① 如果事件到達(dá)胯舷,消息會(huì)被傳遞給響應(yīng)的處理程序來處理,runLoop處理完當(dāng)次事件后绊含,runLoop就會(huì)推出桑嘶,而不管之前預(yù)定的時(shí)間到了沒有。

② 可以重新啟動(dòng)runLoop來等待下一事件躬充;

③ 如果線程中有需要處理的源逃顶,但是響應(yīng)的事件沒有到來的時(shí)候,線程就會(huì)休眠等待相應(yīng)事件的發(fā)生充甚。

4.runLoop的使用

僅當(dāng)在為你的程序創(chuàng)建輔助線程的時(shí)候以政,你才需要顯示運(yùn)行一個(gè)runLoop

對(duì)于輔助線程,你需要判斷一個(gè)runLoop是否是必須的伴找。如果是必須的盈蛮,那么你要自己配置并啟動(dòng)它,你不需要再任何情況下都去啟動(dòng)一個(gè)線程的runLoop技矮。runLoop在你要和線程有更多的交互時(shí)才需要眉反,比如以下情況:

① 使用端口或者自定義輸入源來和其他線程通信;

② 使用線程的定時(shí)器穆役;

③ Cocoa中使用任何performSelector的方法;

④ 使線程周期性工作梳凛。

四耿币、CFRunLoop介紹

1.runLoop對(duì)外的接口

CoreFoundation中有5個(gè)關(guān)于runLoop的類:

① CFRunLoopRef:

② CFRunLoopModeRef:該類并沒有對(duì)外暴露;

③ CFRunLoopSourceRef:時(shí)間產(chǎn)生的地方韧拒,source有兩個(gè)版本:

A.source0:只包含一個(gè)回調(diào)淹接,它并不能主動(dòng)觸發(fā)事件十性,使用時(shí),需先調(diào)用CFRunLoopSourceSignal將這個(gè)source標(biāo)記為待處理塑悼,后調(diào)用CFRunLoopWakeUp來喚醒runLoop劲适,讓其處理這個(gè)事件;

B.source1:包含一個(gè)mach_port和一個(gè)回調(diào)厢蒜,被用于通過內(nèi)核和其他線程相互發(fā)送消息霞势,這種source能主動(dòng)喚醒runLoop線程。

④ CFRunLoopTimerRef:基于事件的觸發(fā)器斑鸦,他和NSTimer是可以混用的愕贡,其包含一個(gè)事件長度和回調(diào),當(dāng)其加入到runLoop中是巷屿,runLoop會(huì)注冊(cè)對(duì)應(yīng)的時(shí)間點(diǎn)固以,當(dāng)時(shí)間點(diǎn)到時(shí),runLoop會(huì)被喚醒以執(zhí)行那個(gè)回調(diào)嘱巾;

⑤ CFRunLoopObserverRef:觀察者憨琳,包含了一個(gè)回調(diào),當(dāng)runLoop的狀態(tài)發(fā)生變化時(shí)旬昭,觀察者就能通過回調(diào)接收到變化篙螟,可觀測的時(shí)間點(diǎn)有:

kCFRunLoopEntry? ? ? ? ? ? ? ? ? ? //即將進(jìn)入Loop

kCFRunLoopBeforeTimers? ? ? ? ? ? ? //即將處理Timer

kCFRunLoopBeforeSources? ? ? ? ? ? //即將處理Source

kCFRunLoopBeforeWaiting? ? ? ? ? ? //即將進(jìn)入休眠

kCFRunLoopAfterWaiting? ? ? ? ? ? ? //剛從休眠中喚醒

kCFRunLoopExit? ? ? ? ? ? ? ? ? ? ? //即將退出Loop

ps:

① 一個(gè)runLoop包含若干個(gè)Mode,每個(gè)Mode包含若干個(gè)Source/Timer/Observer;

② 每次調(diào)用runLoop的主函數(shù)稳懒,只能指定其中一個(gè)Mode闲擦,如果需要切換Mode,只能退出Loop场梆,再重新指定一個(gè)Mode進(jìn)入墅冷;

③ Source/Timer/Observer統(tǒng)稱為mode item,一個(gè)item可以同時(shí)加入多個(gè)mode或油,但一個(gè)item被重復(fù)加入同一個(gè)mode是沒效果的寞忿;

④ 如果一個(gè)mode鐘一個(gè)item都沒有,runLoop就會(huì)退出顶岸,不進(jìn)入循環(huán)腔彰。

2.runLoop的Mode

CFRunLoop的結(jié)構(gòu)如下

struct __CFRunLoop {

CFMutableSetRef _commonModes;

CFMutableSetRef _commonModeItems;

CFRunLoopModeRef _currentMode;

CFMutableSetRef _modes;

...

};

CFRunLoopMode的結(jié)構(gòu)如下:

struct __CFRunLoopMode {

CFStringRef _name;

CFMutableSetRef _sources0;

CFMutableSetRef _sources1;

CFMutableArrayRef _observers;

CFMutableArrayRef _timers;

...

};

其中,CFRunLoop對(duì)外暴露的管理Mode的接口有兩個(gè):

CFRunLoopAddCommonMode

CFRunLoopRunInMode

Mode暴露的管理mode item的接口有下面幾個(gè):

CFRunLoopAddSource

CFRunLoopAddObserver

CFRunLoopAddTimer

CFRunLoopRemoveSource

CFRunLoopRemoveObserver

CFRunLoopRemoveTimer

ps:

① 只能通過mode name來操作內(nèi)部的mode辖佣,當(dāng)你傳入一個(gè)新的mode name但runLoop內(nèi)部沒有對(duì)應(yīng)的Mode時(shí)霹抛,runLoop會(huì)自動(dòng)幫你創(chuàng)建對(duì)應(yīng)的CFRunlLoopModeRef。對(duì)于一個(gè)runLoop來說卷谈,其內(nèi)部的mode只能增加杯拐,而不能刪除。

② commonModes:一個(gè)mode可以將自己標(biāo)記為“Common”蘇醒,每當(dāng)runLoop的內(nèi)容發(fā)生變化時(shí)端逼,runLoop都會(huì)自動(dòng)將_commonModeItems里的item同步到具有“Common”標(biāo)記的所有Mode里朗兵。

3.runLoop的內(nèi)部邏輯

實(shí)際上,runLoop就是一個(gè)函數(shù)顶滩,其內(nèi)部是一個(gè)do-while循環(huán)余掖,當(dāng)你調(diào)用CFRunLoop()時(shí),線程就會(huì)一直停留在這個(gè)循環(huán)中礁鲁;直到超時(shí)或被手動(dòng)停止盐欺,該函數(shù)才會(huì)返回。

五救氯、runLoop的底層實(shí)現(xiàn)

runLoop的核心是基于mach port的找田,其進(jìn)入休眠時(shí)調(diào)用的函數(shù)是mach_msg(),為了解釋這個(gè)邏輯着憨,需要介紹下ios的系統(tǒng)框架墩衙;

1.系統(tǒng)層次

蘋果官方將系統(tǒng)大致劃分為4個(gè)層次:

① 應(yīng)用層:包括用戶能解除到的圖層應(yīng)用,例如Spotlight甲抖、Aqua漆改、SpringBoard等

② 應(yīng)用框架層:即開發(fā)人員解除到的Cocoa等框架;

③ 核心框架層:包括各種核心框架准谚、OpenGL等內(nèi)容挫剑;

④ Darwin:即操作系統(tǒng)的核心,包括系統(tǒng)內(nèi)核柱衔、驅(qū)動(dòng)樊破、Shell等內(nèi)容,這層是開源的

2.Darwin層

其中唆铐,在硬件層上面的三個(gè)組成部分:Mach哲戚,BSD,IOKit艾岂,共同組成了XNU內(nèi)核顺少。

① Mach:XNU內(nèi)核的內(nèi)環(huán)被稱作Mach,其作為一個(gè)為內(nèi)核王浴,僅提供了諸如處理器調(diào)度脆炎、IPC(進(jìn)程間通信)等非常少量的基礎(chǔ)服務(wù);

② BSD:BSD層可以看做圍繞Mach層的一個(gè)外環(huán)氓辣,提供了諸如進(jìn)程管理秒裕、未見系統(tǒng)和網(wǎng)絡(luò)等功能;

③ IOKit:該層為設(shè)備驅(qū)動(dòng)提供了一個(gè)面向?qū)ο螅–++)的框架钞啸。

Mach本身提供的API非常有限几蜻,而且蘋果也不鼓勵(lì)使用Mach的API癞松,但是這些API非常基礎(chǔ)入蛆,如果沒有這些API的話,其他任何工作都無法實(shí)施硕勿。在Mach中哨毁,所有的東西都是通過自己的對(duì)象實(shí)現(xiàn)的,進(jìn)程源武、線程和虛擬內(nèi)存都被稱為“對(duì)象”扼褪。和其他架構(gòu)不公,Mach對(duì)象間不能直接調(diào)用粱栖,只能通過消息傳遞的方式實(shí)現(xiàn)對(duì)象間的通信话浇。“消息”是Mach中最基礎(chǔ)的概念闹究,消息在兩個(gè)端口(port)之間傳遞幔崖,就是Mach的IPC的核心。

為了實(shí)現(xiàn)消息的發(fā)送和接收渣淤,mach_msg()函數(shù)實(shí)際上是調(diào)用了一個(gè)Mach陷阱(trap)即函數(shù)mach_msg_trap()赏寇,陷阱這個(gè)概念在Mach中等同于系統(tǒng)調(diào)用。當(dāng)你在用戶狀態(tài)調(diào)用mach_msg_trap()時(shí)會(huì)觸發(fā)陷阱機(jī)制价认,切換到內(nèi)核態(tài)嗅定;內(nèi)核態(tài)中內(nèi)核實(shí)現(xiàn)mach_msg()函數(shù)會(huì)完成實(shí)際的工作。

ps:runLoop的核心就是一個(gè)mach_msg()用踩,runLoop調(diào)用這個(gè)函數(shù)去接收消息渠退,如果沒有別人發(fā)送port消息過來,內(nèi)核會(huì)將線程置于等待撞他脐彩。

例如你在模擬器里跑起一個(gè)app碎乃,然后在app靜止時(shí)點(diǎn)擊暫停,你會(huì)看到主線程調(diào)用棧是停留在mach_msg_trap()這個(gè)地方丁屎。

六荠锭、蘋果用runLoop實(shí)現(xiàn)的功能

1.AutoReleasePool

app啟動(dòng)后,蘋果在主線程的runLoop里注冊(cè)了兩個(gè)Observer:

① 第一個(gè)Observer監(jiān)視事件是Entry(即將進(jìn)入Loop)晨川,其回調(diào)內(nèi)會(huì)創(chuàng)建自動(dòng)釋放池证九,優(yōu)先級(jí)最高,保證釋放池發(fā)生在所有回調(diào)之前共虑;

② 第二個(gè)Observer監(jiān)視了兩個(gè)事件愧怜,BeforeWaiting(準(zhǔn)備進(jìn)入休眠)時(shí)釋放舊的池并創(chuàng)建新的池;Exit(即將推出loop)時(shí)釋放自動(dòng)釋放池妈拌;優(yōu)先級(jí)最低拥坛,保證其釋放池發(fā)生在其他回調(diào)之后蓬蝶。

2.事件響應(yīng)

蘋果注冊(cè)了一個(gè)Source1(基于mach port)用來接收系統(tǒng)事件

當(dāng)一個(gè)硬件事件(觸摸/搖晃等)發(fā)生后,首先由IOKit.framework生成一個(gè)IOHIDEvent

事件猜惋,并由SpringBoard接收丸氛,隨后用mach port轉(zhuǎn)發(fā)給需要的App進(jìn)程。隨后蘋果注冊(cè)

的那個(gè)Source1會(huì)觸發(fā)回調(diào)著摔,并調(diào)用方法UIApplicationHandleEventQueue()進(jìn)行應(yīng)用內(nèi)

部的分發(fā)缓窜,

UIApplicationHandleEventQueue()方法會(huì)把IOHIDEvent處理并包裝成UIEvent分發(fā),

通常事件比如UIButton點(diǎn)擊谍咆,touch事件都是在這個(gè)回調(diào)中完成的禾锤。

3.手勢識(shí)別

當(dāng)上邊的UIApplicationHandleEventQueue()識(shí)別了手勢后,首先會(huì)打斷當(dāng)前的touch系統(tǒng)回調(diào)摹察,隨后系統(tǒng)將手勢標(biāo)記為待處理恩掷。蘋果注冊(cè)了一個(gè)Observer檢測BeforeWaiting,在這個(gè)事件的回調(diào)函數(shù)中供嚎,獲取所有剛被標(biāo)記為待處理的手勢黄娘,并執(zhí)行手勢的回調(diào)。

4.界面更新

當(dāng)操作UI時(shí)查坪,比如改變了Frame等寸宏,這個(gè)UIView/CALayer會(huì)被標(biāo)記為待處理,并提交到一個(gè)全局的容器中偿曙。

蘋果注冊(cè)了一個(gè)Observer監(jiān)聽BeforeWaiting和Exit氮凝,在回調(diào)用,會(huì)遍歷所有待處理的UIView/CALayer以執(zhí)行實(shí)際的繪制和調(diào)整望忆,并更新UI界面罩阵。

5.定時(shí)器

一個(gè)NSTimer注冊(cè)到RunLoop后,runLoop會(huì)為其重復(fù)的時(shí)間點(diǎn)注冊(cè)號(hào)時(shí)間启摄,runLoop為了節(jié)省資源稿壁,并不會(huì)再非常準(zhǔn)確的時(shí)間點(diǎn)回調(diào)這個(gè)timer。timer有個(gè)屬性叫做tolerance(寬容度)歉备,表示當(dāng)時(shí)間點(diǎn)后傅是,容許有多少最大誤差。

6.PerformSelector

當(dāng)調(diào)用NSObject的PerformSelector方法后蕾羊,實(shí)際上其內(nèi)部會(huì)創(chuàng)建一個(gè)timer并添加到當(dāng)前線程的runLoop中喧笔,如果當(dāng)前線程沒有runLoop,則這個(gè)方法會(huì)失效龟再。

7.關(guān)于GCD

實(shí)際上runLoop底層书闸,也用到了GCD的東西,比如runLoop用dispatch_source_t實(shí)現(xiàn)

的timer利凑,但同時(shí)GCD提供的某些方法也用到了runLoop浆劲,例如dispatch_async()嫌术。

8.關(guān)于網(wǎng)絡(luò)請(qǐng)求

關(guān)于網(wǎng)絡(luò)請(qǐng)求的接口,自上之下有如下基層:

① CFSocket:是最底層的接口牌借,只負(fù)責(zé)socket的通信度气;

② CFNetwork:是基于CFSocket等接口的上層封裝,ASIHttpRequest工作與這層膨报;

③ NSURLConnection:是基于CFNetwork的更高層的封裝蚯嫌,提供面向?qū)ο蟮慕涌冢?/p>

AFNetworking工作于這一層;

④ NSURLSession:是ios7中新增的接口丙躏,表面上和NSURLConnection并列,但底層

仍然用到了NSURLConnection的部分功能束凑,AFNetworking2和Alamofire工作于這層晒旅。

9.NSURLConnection的工作過程

通常使用 NSURLConnection 時(shí),你會(huì)傳入一個(gè) Delegate汪诉,當(dāng)調(diào)用了 [connection start] 后废恋,這個(gè) Delegate 就會(huì)不停收到事件回調(diào)。實(shí)際上扒寄,start 這個(gè)函數(shù)的內(nèi)部會(huì)獲取CurrentRunLoop鱼鼓,然后在其中的 DefaultMode 添加了4個(gè) Source0 (即需要手動(dòng)觸發(fā)的Source) 。CFMultiplexerSource 是負(fù)責(zé)各種 Delegate 回調(diào)的该编,CFHTTPCookieStorage 是處理各種 Cookie 的迄本。

當(dāng)開始網(wǎng)絡(luò)傳輸時(shí),我們可以看到 NSURLConnection 創(chuàng)建了兩個(gè)新線程:com.apple.NSURLConnectionLoader 和 com.apple.CFSocket.private课竣。其中 CFSocket 線程是處理底層 socket 連接的嘉赎。NSURLConnectionLoader 這個(gè)線程內(nèi)部會(huì)使用 RunLoop 來接收底層 socket 的事件,并通過之前添加的 Source0 通知到上層的 Delegate于樟。

NSURLConnectionLoader 中的 RunLoop 通過一些基于 mach port 的 Source 接收來自底層 CFSocket 的通知公条。當(dāng)收到通知后,其會(huì)在合適的時(shí)機(jī)向 CFMultiplexerSource 等 Source0 發(fā)送通知迂曲,同時(shí)喚醒 Delegate 線程的 RunLoop 來讓其處理這些通知靶橱。

CFMultiplexerSource 會(huì)在 Delegate 線程的 RunLoop 對(duì) Delegate 執(zhí)行實(shí)際的回調(diào)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末路捧,一起剝皮案震驚了整個(gè)濱河市关霸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鬓长,老刑警劉巖谒拴,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異涉波,居然都是意外死亡英上,警方通過查閱死者的電腦和手機(jī)炭序,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來苍日,“玉大人惭聂,你說我怎么就攤上這事∠嗍眩” “怎么了辜纲?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長拦耐。 經(jīng)常有香客問我耕腾,道長,這世上最難降的妖魔是什么杀糯? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任扫俺,我火速辦了婚禮,結(jié)果婚禮上固翰,老公的妹妹穿的比我還像新娘狼纬。我一直安慰自己,他們只是感情好骂际,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布疗琉。 她就那樣靜靜地躺著,像睡著了一般歉铝。 火紅的嫁衣襯著肌膚如雪盈简。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天太示,我揣著相機(jī)與錄音送火,去河邊找鬼。 笑死先匪,一個(gè)胖子當(dāng)著我的面吹牛种吸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播呀非,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼坚俗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了岸裙?” 一聲冷哼從身側(cè)響起猖败,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎降允,沒想到半個(gè)月后恩闻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡剧董,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年幢尚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了破停。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡尉剩,死狀恐怖真慢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情理茎,我是刑警寧澤黑界,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站皂林,受9級(jí)特大地震影響朗鸠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜础倍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一童社、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧著隆,春花似錦、人聲如沸呀癣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽项栏。三九已至浦辨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間沼沈,已是汗流浹背流酬。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留列另,地道東北人芽腾。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像页衙,于是被迫代替她去往敵國和親摊滔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

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