從 NSURLConnection 到 NSURLSession

轉(zhuǎn)載自https://objccn.io/issue-5-4/
從 NSURLConnection 到 NSURLSession
方一雄
2014/04/11

iOS 7 和 Mac OS X 10.9 Mavericks 中一個(gè)顯著的變化就是對(duì) Foundation URL 加載系統(tǒng)的徹底重構(gòu)。
現(xiàn)在已經(jīng)有人在深入蘋果的網(wǎng)絡(luò)層基礎(chǔ)架構(gòu)的地方做研究了,所以我想是時(shí)候來分享一些對(duì)于我對(duì)于這些新的 API 的看法和心得了放航,新的 API 將如何影響我們編寫程序蜕青,以及它們對(duì)于 API 設(shè)計(jì)理念的影響。
NSURLConnection
作為 Core Foundation / CFNetwork 框架的 API 之上的一個(gè)抽象怀薛,在 2003 年,隨著第一版的 Safari 的發(fā)布就發(fā)布了。NSURLConnection
這個(gè)名字傍药,實(shí)際上是指代的 Foundation 框架的 URL 加載系統(tǒng)中一系列有關(guān)聯(lián)的組件:NSURLRequest
、NSURLResponse
魂仍、NSURLProtocol
拐辽、NSURLCache
、NSHTTPCookieStorage
擦酌、NSURLCredentialStorage
以及同名類NSURLConnection
俱诸。
NSURLRequest
被傳遞給NSURLConnection
。被委托對(duì)象(遵守以前的非正式協(xié)議<NSURLConnectionDelegate>
和<NSURLConnectionDataDelegate>
)異步地返回一個(gè)NSURLResponse
以及包含服務(wù)器返回信息的NSData
赊舶。
在一個(gè)請(qǐng)求被發(fā)送到服務(wù)器之前睁搭,系統(tǒng)會(huì)先查詢共享的緩存信息,然后根據(jù)策略(policy)以及可用性(availability)的不同笼平,一個(gè)已經(jīng)被緩存的響應(yīng)可能會(huì)被立即返回园骆。如果沒有緩存的響應(yīng)可用,則這個(gè)請(qǐng)求將根據(jù)我們指定的策略來緩存它的響應(yīng)以便將來的請(qǐng)求可以使用寓调。
在把請(qǐng)求發(fā)送給服務(wù)器的過程中锌唾,服務(wù)器可能會(huì)發(fā)出鑒權(quán)查詢(authentication challenge),這可以由共享的 cookie 或機(jī)密存儲(chǔ)(credential storage)來自動(dòng)響應(yīng)夺英,或者由被委托對(duì)象來響應(yīng)晌涕。發(fā)送中的請(qǐng)求也可以被注冊(cè)的NSURLProtocol
對(duì)象所攔截,以便在必要的時(shí)候無縫地改變其加載行為痛悯。
不管怎樣余黎,NSURLConnection
作為網(wǎng)絡(luò)基礎(chǔ)架構(gòu),已經(jīng)服務(wù)了成千上萬的 iOS 和 Mac OS 程序载萌,并且做的還算相當(dāng)不錯(cuò)惧财。但是這些年亲族,一些用例——尤其是在 iPhone 和 iPad 上面——已經(jīng)對(duì)NSURLConnection
的幾個(gè)核心概念提出了挑戰(zhàn),讓蘋果有理由對(duì)它進(jìn)行重構(gòu)可缚。
在 2013 的 WWDC 上霎迫,蘋果推出了NSURLConnection
的繼任者:NSURLSession

和NSURLConnection
一樣帘靡,NSURLSession
指的也不僅是同名類NSURLSession
知给,還包括一系列相互關(guān)聯(lián)的類。NSURLSession
包括了與之前相同的組件描姚,NSURLRequest
與NSURLCache
涩赢,但是把NSURLConnection
替換成了NSURLSession
、NSURLSessionConfiguration
以及NSURLSessionTask
的 3 個(gè)子類:NSURLSessionDataTask
轩勘,NSURLSessionUploadTask
筒扒,NSURLSessionDownloadTask

與NSURLConnection
相比绊寻,NSURLsession
最直接的改進(jìn)就是可以配置每個(gè) session 的緩存花墩,協(xié)議,cookie澄步,以及證書策略(credential policy)冰蘑,甚至跨程序共享這些信息。這將允許程序和網(wǎng)絡(luò)基礎(chǔ)框架之間相互獨(dú)立村缸,不會(huì)發(fā)生干擾祠肥。每個(gè)NSURLSession
對(duì)象都由一個(gè)NSURLSessionConfiguration
對(duì)象來進(jìn)行初始化,后者指定了剛才提到的那些策略以及一些用來增強(qiáng)移動(dòng)設(shè)備上性能的新選項(xiàng)梯皿。
NSURLSession
中另一大塊就是 session task仇箱。它負(fù)責(zé)處理數(shù)據(jù)的加載以及文件和數(shù)據(jù)在客戶端與服務(wù)端之間的上傳和下載。NSURLSessionTask
與NSURLConnection
最大的相似之處在于它也負(fù)責(zé)數(shù)據(jù)的加載东羹,最大的不同之處在于所有的 task 共享其創(chuàng)造者NSURLSession
這一公共委托者(common delegate)剂桥。
我們先來深入探討 task,過后再來討論NSURLSessionConfiguration
百姓。
NSURLSessionTask
NSURLsessionTask
是一個(gè)抽象類渊额,其下有 3 個(gè)實(shí)體子類可以直接使用:NSURLSessionDataTask
、NSURLSessionUploadTask
垒拢、NSURLSessionDownloadTask
旬迹。這 3 個(gè)子類封裝了現(xiàn)代程序三個(gè)最基本的網(wǎng)絡(luò)任務(wù):獲取數(shù)據(jù),比如 JSON 或者 XML求类,上傳文件和下載文件奔垦。

NSURLSessionTask class diagram
NSURLSessionTask class diagram

當(dāng)一個(gè)NSURLSessionDataTask
完成時(shí),它會(huì)帶有相關(guān)聯(lián)的數(shù)據(jù)尸疆,而一個(gè)NSURLSessionDownloadTask
任務(wù)結(jié)束時(shí)椿猎,它會(huì)帶回已下載文件的一個(gè)臨時(shí)的文件路徑惶岭。因?yàn)橐话銇碚f,服務(wù)端對(duì)于一個(gè)上傳任務(wù)的響應(yīng)也會(huì)有相關(guān)數(shù)據(jù)返回犯眠,所以NSURLSessionUploadTask
繼承自NSURLSessionDataTask
按灶。
所有的 task 都是可以取消,暫涂疬郑或者恢復(fù)的鸯旁。當(dāng)一個(gè) download task 取消時(shí),可以通過選項(xiàng)來創(chuàng)建一個(gè)恢復(fù)數(shù)據(jù)(resume data)量蕊,然后可以傳遞給下一次新創(chuàng)建的 download task铺罢,以便繼續(xù)之前的下載。
不同于直接使用alloc-init
初始化方法残炮,task 是由一個(gè)NSURLSession
創(chuàng)建的韭赘。每個(gè) task 的構(gòu)造方法都對(duì)應(yīng)有或者沒有completionHandler
這個(gè) block 的兩個(gè)版本,例如:有這樣兩個(gè)構(gòu)造方法–dataTaskWithRequest:
和–dataTaskWithRequest:completionHandler:
势就。這與NSURLConnection
的-sendAsynchronousRequest:queue:completionHandler:
方法類似泉瞻,通過指定completionHandler
這個(gè) block 將創(chuàng)建一個(gè)隱式的 delegate,來替代該 task 原來的 delegate——session蛋勺。對(duì)于需要 override 原有 session task 的 delegate 的默認(rèn)行為的情況瓦灶,我們需要使用這種不帶completionHandler
的版本鸠删。
NSURLSessionTask 的工廠方法
在 iOS 5 中抱完,NSURLConnection
添加了sendAsynchronousRequest:queue:completionHandler:
這一方法,對(duì)于一次性使用的 request刃泡, 大大地簡(jiǎn)化代碼巧娱,同時(shí)它也是sendSynchronousRequest:returningResponse:error:
這個(gè)方法的異步替代品:

NSURL *URL = [NSURL URLWithString:@"http://example.com"]; 
NSURLRequest *request = [NSURLRequest requestWithURL:URL]; 
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { // ... }];

NSURLSession
在 task 的構(gòu)造方法上延續(xù)了這一模式。不同的是烘贴,這里不會(huì)立即運(yùn)行 task禁添,而是將該 task 對(duì)象先返回,允許我們進(jìn)一步的配置桨踪,然后可以使用resume
方法來讓它開始運(yùn)行老翘。
Data task 可以通過NSURL
或NSURLRequest
創(chuàng)建(使用前者相當(dāng)于是使用一個(gè)對(duì)于該 URL 進(jìn)行標(biāo)準(zhǔn)GET
請(qǐng)求的NSURLRequest
,這是一種快捷方法):

NSURL *URL = [NSURL URLWithString:@"http://example.com"]; 
NSURLRequest *request = [NSURLRequest requestWithURL:URL]; 
NSURLSession *session = [NSURLSession sharedSession]; NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) { // ... }]; [task resume];

Upload task 的創(chuàng)建需要使用一個(gè) request锻离,另外加上一個(gè)要上傳的NSData
對(duì)象或者是一個(gè)本地文件的路徑對(duì)應(yīng)的NSURL

NSURL *URL = [NSURL URLWithString:@"http://example.com/upload"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL]; 
NSData *data = ...;
NSURLSession *session = [NSURLSession sharedSession]; 
NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:data completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error) { // ... }]; [uploadTask resume];

Download task 也需要一個(gè) request铺峭,不同之處在于completionHandler
這個(gè) block。Data task 和 upload task 會(huì)在任務(wù)完成時(shí)一次性返回汽纠,但是 Download task 是將數(shù)據(jù)一點(diǎn)點(diǎn)地寫入本地的臨時(shí)文件卫键。所以在completionHandler
這個(gè) block 里,我們需要把文件從一個(gè)臨時(shí)地址移動(dòng)到一個(gè)永久的地址保存起來:

NSURL *URL = [NSURL URLWithString:@"http://example.com/file.zip"]; 
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSession *session = [NSURLSession sharedSession]; 
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler: ^(NSURL *location, NSURLResponse *response, NSError *error) { NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; 
NSURL *documentsDirectoryURL = [NSURL fileURLWithPath:documentsPath]; 
NSURL *newFileLocation = [documentsDirectoryURL URLByAppendingPathComponent:[[response URL] lastPathComponent]]; 
[[NSFileManager defaultManager] copyItemAtURL:location toURL:newFileLocation error:nil]; }];
 [downloadTask resume];

編者注 原文中這塊代碼以及上文的表述中存有一些問題虱朵,詳見這個(gè) issue莉炉,本文已進(jìn)行更正钓账,如果您有不同意見,歡迎在 Github 上給我們反饋絮宁。

NSURLSession 與 NSURLConnection 的 delegate 方法
總體而言梆暮,NSURLSession
的 delegate 方法是NSURLConnection
的演化的十年中對(duì)于 ad-hoc 模式的一個(gè)顯著改善。您可以查看這個(gè)映射表來進(jìn)行一個(gè)完整的概覽绍昂。
以下是一些具體的觀察:
NSURLSession
既擁有 seesion 的 delegate 方法惕蹄,又擁有 task 的 delegate 方法用來處理鑒權(quán)查詢。session 的 delegate 方法處理連接層的問題治专,諸如服務(wù)器信任卖陵,客戶端證書的評(píng)估,NTLM 和 Kerberos 協(xié)議這類問題张峰,而 task 的 delegate 則處理以網(wǎng)絡(luò)請(qǐng)求為基礎(chǔ)的問題泪蔫,如 Basic,Digest喘批,以及代理身份驗(yàn)證(Proxy authentication)等撩荣。
在NSURLConnection
中有兩個(gè) delegate 方法可以表明一個(gè)網(wǎng)絡(luò)請(qǐng)求已經(jīng)結(jié)束:NSURLConnectionDataDelegate
中的-connectionDidFinishLoading:
和NSURLConnectionDelegate
中的-connection:didFailWithError:
,而在NSURLSession
中改為一個(gè) delegate 方法:NSURLSessionTaskDelegate
的-URLSession:task:didCompleteWithError:

NSURLSession
中表示傳輸多少字節(jié)的參數(shù)類型現(xiàn)在改為int64_t
饶深,以前在NSURLConnection
中相應(yīng)的參數(shù)的類型是long long
餐曹。
由于增加了completionHandler:
這個(gè) block 作為參數(shù),NSURLSession
實(shí)際上給 Foundation 框架引入了一種全新的模式敌厘。這種模式允許 delegate 方法可以安全地在主線程與運(yùn)行台猴,而不會(huì)阻塞主線程;Delgate 只需要簡(jiǎn)單地調(diào)用dispatch_async
就可以切換到后臺(tái)進(jìn)行相關(guān)的操作俱两,然后在操作完成時(shí)調(diào)用completionHandler
即可饱狂。同時(shí),它還可以有效地?fù)碛卸鄠€(gè)返回值宪彩,而不需要我們使用笨拙的參數(shù)指針休讳。以NSURLSessionTaskDelegate
的-URLSession:task:didReceiveChallenge:completionHandler:
方法來舉例,completionHandler
接受兩個(gè)參數(shù):NSURLSessionAuthChallengeDisposition
和NSURLCredential
尿孔,前者為應(yīng)對(duì)鑒權(quán)查詢的策略俊柔,后者為需要使用的證書(僅當(dāng)前者——應(yīng)對(duì)鑒權(quán)查詢的策略為使用證書,即NSURLSessionAuthChallengeUseCredential
時(shí)有效活合,否則該參數(shù)為NULL

想要查看更多關(guān)于 session task 的信息雏婶,可以查看 WWDC Session 705: "What’s New in Foundation Networking"

NSURLSessionConfiguration
NSURLSessionConfiguration
對(duì)象用于對(duì)NSURLSession
對(duì)象進(jìn)行初始化。NSURLSessionConfiguration
對(duì)以前NSMutableURLRequest
所提供的網(wǎng)絡(luò)請(qǐng)求層的設(shè)置選項(xiàng)進(jìn)行了擴(kuò)充芜辕,提供給我們相當(dāng)大的靈活性和控制權(quán)尚骄。從指定可用網(wǎng)絡(luò),到 cookie侵续,安全性倔丈,緩存策略憨闰,再到使用自定義協(xié)議,啟動(dòng)事件的設(shè)置需五,以及用于移動(dòng)設(shè)備優(yōu)化的幾個(gè)新屬性鹉动,你會(huì)發(fā)現(xiàn)使用NSURLSessionConfiguration
可以找到幾乎任何你想要進(jìn)行配置的選項(xiàng)。
NSURLSession
在初始化時(shí)會(huì)把配置它的NSURLSessionConfiguration
對(duì)象進(jìn)行一次 copy宏邮,并保存到自己的configuration
屬性中泽示,而且這個(gè)屬性是只讀的。因此之后再修改最初配置 session 的那個(gè) configuration 對(duì)象對(duì)于 session 是沒有影響的蜜氨。也就是說械筛,configuration 只在初始化時(shí)被讀取一次,之后都是不會(huì)變化的飒炎。
NSURLSessionConfiguration 的工廠方法
NSURLSessionConfiguration
有三個(gè)類工廠方法埋哟,這很好地說明了NSURLSession
設(shè)計(jì)時(shí)所考慮的不同的使用場(chǎng)景。
+defaultSessionConfiguration
返回一個(gè)標(biāo)準(zhǔn)的 configuration郎汪,這個(gè)配置實(shí)際上與NSURLConnection
網(wǎng)絡(luò)堆棧(networking stack)是一樣的攻旦,具有相同的共享NSHTTPCookieStorage
吭狡,共享NSURLCache
和共享NSURLCredentialStorage
谎替。
+ephemeralSessionConfiguration
返回一個(gè)預(yù)設(shè)配置床嫌,這個(gè)配置中不會(huì)對(duì)緩存,Cookie 和證書進(jìn)行持久性的存儲(chǔ)照筑。這對(duì)于實(shí)現(xiàn)像秘密瀏覽這種功能來說是很理想的吹截。
+backgroundSessionConfiguration:(NSString )identifier
的獨(dú)特之處在于,它會(huì)創(chuàng)建一個(gè)
后臺(tái) session朦肘。后臺(tái) session 不同于常規(guī)的饭弓,普通的 session,它甚至可以在應(yīng)用程序掛起媒抠,退出或者崩潰的情況下運(yùn)行上傳和下載任務(wù)。初始化時(shí)指定的標(biāo)識(shí)符咏花,被用于向任何可能在進(jìn)程外恢復(fù)后臺(tái)傳輸?shù)?/em>守護(hù)進(jìn)程(daemon)提供上下文趴生。
想要查看更多關(guān)于后臺(tái) session 的信息,可以查看 WWDC Session 204: "What's New with Multitasking"
配置屬性
NSURLSessionConfiguration
擁有 20 個(gè)配置屬性昏翰。熟練掌握這些配置屬性的用處苍匆,可以讓應(yīng)用程序充分地利用其網(wǎng)絡(luò)環(huán)境。
基本配置
HTTPAdditionalHeaders
指定了一組默認(rèn)的可以設(shè)置
出站請(qǐng)求(outbound request)*的數(shù)據(jù)頭棚菊。這對(duì)于跨 session 共享信息浸踩,如內(nèi)容類型,語言统求,用戶代理和身份認(rèn)證检碗,是很有用的据块。

NSString *userPasswordString = [NSString stringWithFormat:@"%@:%@", user, password];NSData * userPasswordData = [userPasswordString dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64EncodedCredential = [userPasswordData base64EncodedStringWithOptions:0];
NSString *authString = [NSString stringWithFormat:@"Basic %@", base64EncodedCredential];
NSString *userAgentString = @"AppName/com.example.app (iPhone 5s; iOS 7.0.2; Scale/2.0)";configuration.HTTPAdditionalHeaders = @{@"Accept": @"application/json", @"Accept-Language": @"en", @"Authorization": authString, @"User-Agent": userAgentString};

networkServiceType
對(duì)標(biāo)準(zhǔn)的網(wǎng)絡(luò)流量,網(wǎng)絡(luò)電話折剃,語音另假,視頻,以及由一個(gè)后臺(tái)進(jìn)程使用的流量進(jìn)行了區(qū)分怕犁。大多數(shù)應(yīng)用程序都不需要設(shè)置這個(gè)边篮。
allowsCellularAccess
和discretionary
被用于節(jié)省通過蜂窩網(wǎng)絡(luò)連接的帶寬。對(duì)于后臺(tái)傳輸?shù)那闆r奏甫,推薦大家使用discretionary
這個(gè)屬性戈轿,而不是allowsCellularAccess
,因?yàn)榍罢邥?huì)把 WiFi 和電源的可用性考慮在內(nèi)阵子。
timeoutIntervalForRequest
和timeoutIntervalForResource
分別指定了對(duì)于請(qǐng)求和資源的超時(shí)間隔凶杖。許多開發(fā)人員試圖使用timeoutInterval
去限制發(fā)送請(qǐng)求的總時(shí)間,但其實(shí)它真正的含義是:分組(packet)之間的時(shí)間款筑。實(shí)際上我們應(yīng)該使用timeoutIntervalForResource
來規(guī)定整體超時(shí)的總時(shí)間智蝠,但應(yīng)該只將其用于后臺(tái)傳輸,而不是用戶實(shí)際上可能想要去等待的任何東西奈梳。
HTTPMaximumConnectionsPerHost
是 Foundation 框架中 URL 加載系統(tǒng)的一個(gè)新的配置選項(xiàng)杈湾。它曾經(jīng)被NSURLConnection
用于管理私有的連接池。現(xiàn)在有了NSURLSession
攘须,開發(fā)者可以在需要時(shí)限制連接到特定主機(jī)的數(shù)量漆撞。
HTTPShouldUsePipelining
這個(gè)屬性在NSMutableURLRequest
下也有,它可以被用于開啟 HTTP 管線化(HTTP pipelining)于宙,這可以顯著降低請(qǐng)求的加載時(shí)間浮驳,但是由于沒有被服務(wù)器廣泛支持,默認(rèn)是禁用的捞魁。
sessionSendsLaunchEvents
是另一個(gè)新的屬性至会,該屬性指定該 session 是否應(yīng)該從后臺(tái)啟動(dòng)。
connectionProxyDictionary
指定了 session 連接中的代理服務(wù)器谱俭。同樣地奉件,大多數(shù)面向消費(fèi)者的應(yīng)用程序都不需要代理,所以基本上不需要配置這個(gè)屬性昆著。
關(guān)于連接代理的更多信息可以在 CFProxySupport
Reference 找到县貌。

Cookie 策略
HTTPCookieStorage
存儲(chǔ)了 session 所使用的 cookie。默認(rèn)情況下會(huì)使用NSHTTPCookieShorage
的+sharedHTTPCookieStorage
這個(gè)單例對(duì)象凑懂,這與NSURLConnection
是相同的煤痕。
HTTPCookieAcceptPolicy
決定了什么情況下 session 應(yīng)該接受從服務(wù)器發(fā)出的 cookie。
HTTPShouldSetCookies
指定了請(qǐng)求是否應(yīng)該使用 session 存儲(chǔ)的 cookie,即HTTPCookieSorage
屬性的值摆碉。
安全策略
URLCredentialStorage
存儲(chǔ)了 session 所使用的證書塘匣。默認(rèn)情況下會(huì)使用NSURLCredentialStorage
的+sharedCredentialStorage
這個(gè)單例對(duì)象,這與NSURLConnection
是相同的兆解。
TLSMaximumSupportedProtocol
和TLSMinimumSupportedProtocol
確定 session 是否支持 SSL 協(xié)議馆铁。
緩存策略
URLCache
是 session 使用的緩存。默認(rèn)情況下會(huì)使用NSURLCache
的+sharedURLCache
這個(gè)單例對(duì)象锅睛,這與NSURLConnection
是相同的埠巨。
requestCachePolicy
指定了一個(gè)請(qǐng)求的緩存響應(yīng)應(yīng)該在什么時(shí)候返回。這相當(dāng)于NSURLRequest
的-cachePolicy
方法现拒。
自定義協(xié)議
protocolClasses
用來配置特定某個(gè) session 所使用的自定義協(xié)議(該協(xié)議是NSURLProtocol
的子類)的數(shù)組辣垒。
結(jié)論
iOS 7 和 Mac OS X 10.9 Mavericks 中 URL 加載系統(tǒng)的變化,是對(duì)NSURLConnection
進(jìn)行深思熟慮后的一個(gè)自然而然的進(jìn)化印蔬⊙埃總體而言,蘋果的 Foundation 框架團(tuán)隊(duì)干了一件令人欽佩的的工作侥猬,他們研究并預(yù)測(cè)了移動(dòng)開發(fā)者現(xiàn)有的和新興的用例例驹,創(chuàng)造了能夠滿足日常任務(wù)而且非常好用的 API 。
盡管在這個(gè)體系結(jié)構(gòu)中退唠,某些決定對(duì)于可組合性和可擴(kuò)展性而言是一種倒退鹃锈,但是NSURLSession
仍然是實(shí)現(xiàn)更高級(jí)別網(wǎng)絡(luò)功能的一個(gè)強(qiáng)大的基礎(chǔ)框架。
原文 From NSURLConnection to NSURLSession

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末瞧预,一起剝皮案震驚了整個(gè)濱河市屎债,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌垢油,老刑警劉巖盆驹,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異滩愁,居然都是意外死亡躯喇,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門惊楼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來玖瘸,“玉大人,你說我怎么就攤上這事檀咙。” “怎么了璃诀?”我有些...
    開封第一講書人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵弧可,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng)棕诵,這世上最難降的妖魔是什么裁良? 我笑而不...
    開封第一講書人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮校套,結(jié)果婚禮上价脾,老公的妹妹穿的比我還像新娘。我一直安慰自己笛匙,他們只是感情好侨把,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著妹孙,像睡著了一般秋柄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蠢正,一...
    開封第一講書人閱讀 51,610評(píng)論 1 305
  • 那天骇笔,我揣著相機(jī)與錄音,去河邊找鬼嚣崭。 笑死笨触,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的雹舀。 我是一名探鬼主播芦劣,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼葱跋!你這毒婦竟也來了持寄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤娱俺,失蹤者是張志新(化名)和其女友劉穎稍味,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體荠卷,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡模庐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了油宜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掂碱。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖慎冤,靈堂內(nèi)的尸體忽然破棺而出疼燥,到底是詐尸還是另有隱情,我是刑警寧澤蚁堤,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布醉者,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏撬即。R本人自食惡果不足惜立磁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望剥槐。 院中可真熱鬧唱歧,春花似錦、人聲如沸粒竖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽温圆。三九已至挨摸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間岁歉,已是汗流浹背得运。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留锅移,地道東北人熔掺。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像非剃,于是被迫代替她去往敵國(guó)和親置逻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355

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

  • iOS 7 和 Mac OS X 10.9 Mavericks 中一個(gè)顯著的變化就是對(duì) Foundation UR...
    kobehjk閱讀 240評(píng)論 0 2
  • 半夜睡不著备绽,寫一點(diǎn)美好的事物券坞。 一、城市篇(在世界化高速發(fā)展的今天肺素,城市還是各有不同恨锚。) 1.曼谷 (一個(gè)充滿...
    汐曼閱讀 494評(píng)論 0 0
  • 漫天的灰燼與火星在我身邊飄蕩 我感覺我要窒息了,快昏迷的那種窒息 站不起來倍靡,睜不開眼猴伶,說不出話,默默忍受 這溫水要...
    白森丶閱讀 104評(píng)論 0 0
  • 【原文】子曰:“君子無所爭(zhēng)塌西,必也射乎他挎!揖讓而升,下而飲捡需,其爭(zhēng)也君子办桨。” 【譯文】孔子說:“君子沒有什么與人相爭(zhēng)的事...
    轉(zhuǎn)念館閱讀 1,535評(píng)論 0 0
  • 11月27日贸街,禮拜一庵寞,再過一周就十二月狸相,十二月結(jié)束,2018年就開始啦>璐āEЬ椤!古沥! ⒈曾經(jīng)開玩笑瘸右,像我,不喜歡美食岩齿!不...
    李豫一閱讀 200評(píng)論 0 0