[iOS-Foundation] NSURLSession

一個(gè) NSURLSession 對(duì)象代表了一個(gè) session(會(huì)話),這個(gè) session 可以類(lèi)比為瀏覽器的一個(gè) tab 或者負(fù)責(zé)某一類(lèi)請(qǐng)求例如后臺(tái)下載的環(huán)境皿淋,它創(chuàng)建并管理著一組 NSURLSessionTask谬盐,每個(gè)NSURLSessionTask對(duì)象則對(duì)應(yīng)了一個(gè)特定的請(qǐng)求程剥。

當(dāng)創(chuàng)建一個(gè)NSURLSession對(duì)象時(shí)变过,需要一個(gè)提供配置信息的
NSURLSessionConfiguration 對(duì)象,這個(gè)配置信息對(duì)象定義了同一域名的最大連接數(shù)症脂、移動(dòng)網(wǎng)絡(luò)下是否可請(qǐng)求谚赎、請(qǐng)求的緩存和 cookie 保存策略等行為淫僻,session 中的所有 task 共用這個(gè)配置。

注意區(qū)別于 HTTP 協(xié)議中的 session 概念壶唤。HTTP 本身是無(wú)狀態(tài)的協(xié)議雳灵,請(qǐng)求之間是沒(méi)有聯(lián)系的,所以 web 應(yīng)用為了保存用戶登錄狀態(tài)闸盔,返回用戶信息悯辙,就需要用到會(huì)話技術(shù)。HTTP 會(huì)話的原理是迎吵,當(dāng)需要開(kāi)啟一個(gè)會(huì)話時(shí)躲撰,服務(wù)器端會(huì)生成一個(gè) session ID 并保存到客戶端的 cookie 中,之后客戶端的請(qǐng)求帶有的 cookie 里就有了其對(duì)應(yīng)會(huì)話的 session ID击费,服務(wù)器通過(guò)這個(gè) session ID 就可以去獲取到保存在服務(wù)器端的對(duì)應(yīng)的會(huì)話信息拢蛋,并做相應(yīng)處理了。session 的信息可以保存在服務(wù)器的臨時(shí)文件中蔫巩,也可以用 redis 來(lái)保存 session 信息谆棱。

創(chuàng)建 session

  • sharedSession,共享的單例 session 對(duì)象批幌,不需要通過(guò) configuration 和 delegate 來(lái)創(chuàng)建础锐,只提供獲取資源到內(nèi)存中的支持。因?yàn)?session 對(duì)象的 delegate 屬性為只讀荧缘,所以無(wú)法設(shè)置sharedSession的delegate。shared session 使用了共享的
    NSURLCache拦宣、NSHTTPCookieStorageNSURLCredentialStorage對(duì)象截粗。
  • - sessionWithConfiguration:,根據(jù)不同的NSURLSessionConfiguration對(duì)象(default鸵隧、ephemeral 或 background)創(chuàng)建 session 對(duì)象绸罗。
  • - sessionWithConfiguration:delegate:delegateQueue:,根據(jù) configuration 對(duì)象創(chuàng)建 session 的同時(shí)豆瘫,設(shè)置 session 對(duì)象的 delegate 和 delegate queue珊蟀。

session 相關(guān)屬性

  • configuration,session 的 configuration 對(duì)象的 copy外驱,修改這個(gè) configuration 對(duì)象并不會(huì)影響 session育灸,可用于創(chuàng)建新的 session。
  • delegate昵宇,創(chuàng)建 session 時(shí)傳入的 delegate磅崭,session 對(duì)delegate 強(qiáng)引用,只有當(dāng) session 執(zhí)行 invalidate 相關(guān)方法后瓦哎,才會(huì)釋放引用砸喻。
  • delegateQueue柔逼,創(chuàng)建 session 時(shí)傳入的 delegateQueue,所有的代理方法和 block 回調(diào)都會(huì)在這個(gè) queue 中執(zhí)行割岛。
  • sessionDescription愉适,可給 session 設(shè)置一個(gè)描述,用于調(diào)試或界面顯示癣漆。

創(chuàng)建 task

根據(jù)請(qǐng)求的不同需求维咸,session 可以創(chuàng)建 data task、download task扑媚、upload task 和 stream task腰湾。

// data task
- dataTaskWithURL:
- dataTaskWithURL:completionHandler:
- dataTaskWithRequest:
- dataTaskWithRequest:completionHandler:
// download task
- downloadTaskWithURL:
- downloadTaskWithURL:completionHandler:
- downloadTaskWithRequest:
- downloadTaskWithRequest:completionHandler:
- downloadTaskWithResumeData:
- downloadTaskWithResumeData:completionHandler:
// upload task
- uploadTaskWithRequest:fromData:
- uploadTaskWithRequest:fromData:completionHandler:
- uploadTaskWithRequest:fromFile:
- uploadTaskWithRequest:fromFile:completionHandler:
- uploadTaskWithStreamedRequest:
// session task
- streamTaskWithHostName:port:
- streamTaskWithNetService:

如果傳入了 completionHandler 參數(shù),那么 delegate 中返回?cái)?shù)據(jù)疆股、返回響應(yīng)费坊、請(qǐng)求完成等方法都不會(huì)再調(diào)用,但其他 delegate 方法還是會(huì)調(diào)用旬痹,如證書(shū)鑒定等附井。

調(diào)用 completionHandler 會(huì)傳入3個(gè)參數(shù),第一個(gè)參數(shù)是返回的數(shù)據(jù)两残,data task 和 upload task 為NSData類(lèi)型永毅,download task 為臨時(shí)文件保存路徑的NSURL對(duì)象,該文件在回調(diào)執(zhí)行完后會(huì)被刪除人弓,所以要在回調(diào)中做相應(yīng)的持久化處理沼死。后兩個(gè)參數(shù)是NSURLResponce類(lèi)型的 response 和NSError類(lèi)型的 error。

對(duì)于 HTTP 協(xié)議來(lái)說(shuō)崔赌,無(wú)論服務(wù)器返回的響應(yīng) code 是成功還是失敗意蛀,以 task 的角度看,這個(gè)請(qǐng)求 task 是成功的健芭,data 中會(huì)包含返回的內(nèi)容县钥,response 代表了響應(yīng)的元信息,error 則為 nil慈迈,如果發(fā)生客戶端相關(guān)錯(cuò)誤導(dǎo)致 task 請(qǐng)求失敗若贮,error 中則會(huì)包含相關(guān)信息。如果創(chuàng)建 task 時(shí)傳入的是NSURLRequest對(duì)象而不是NSURL對(duì)象痒留,那么 task 除了請(qǐng)求 request 中的 URL 指定的資源谴麦,相關(guān)的請(qǐng)求行為,如請(qǐng)求方法(GET or POST)狭瞎、緩存策略细移、超時(shí)時(shí)間、請(qǐng)求體內(nèi)容等熊锭,也都會(huì)根據(jù) request 對(duì)象設(shè)置弧轧,而這可能會(huì)覆蓋 configuration 中指定的某些行為雪侥。

另外 download task 還可以根據(jù)下載中斷時(shí)的 resume data 創(chuàng)建。調(diào)用 download task 的- cancelByProducingResumeData:方法會(huì)在回調(diào)中返回 resume data精绎,另一種可能獲得 resume data 的情況是速缨,在 download task 失敗時(shí),返回的 error 的 userInfo 里 keyNSURLSessionDownloadTaskResumeData對(duì)應(yīng)保存了 resume data代乃。

而 upload task 的創(chuàng)建必須傳入NSURLRequest對(duì)象旬牲,上傳的內(nèi)容可以通過(guò)參數(shù)傳入NSData對(duì)象或代表文件路徑的NSURL對(duì)象。對(duì)于
- uploadTaskWithStreamedRequest:方法搁吓,則必須實(shí)現(xiàn)代理方法
URLSession:task:needNewBodyStream:用以提供上傳內(nèi)容原茅。

管理 session

session 和 task 的實(shí)例可以不需要應(yīng)用來(lái)維護(hù),系統(tǒng)會(huì)維護(hù)創(chuàng)建的 session 實(shí)例堕仔,而 task 實(shí)例由創(chuàng)建它的 session 維護(hù)擂橘,當(dāng)一個(gè) task 執(zhí)行完成,如果沒(méi)有其他引用摩骨,則會(huì)被銷(xiāo)毀通贞,當(dāng) session 調(diào)用了 invalidate 方法,如果沒(méi)有其他引用恼五,則會(huì)被銷(xiāo)毀昌罩。

- finishTasksAndInvalidate
- invalidateAndCancel

當(dāng)對(duì) session invalidate 后,就不能再創(chuàng)建新的 task 了灾馒,兩個(gè)方法的不同之處是茎用,- finishTasksAndInvalidate會(huì)等到正在執(zhí)行的 task 執(zhí)行完成,調(diào)用完所有回調(diào)或 delegate 后睬罗,釋放對(duì) delegate 的強(qiáng)引用绘搞,而- invalidateAndCancel方法則是直接取消所有正在執(zhí)行的 task。

- flushWithCompletionHandler:

將內(nèi)存中的 cookie傅物、證書(shū)等寫(xiě)到硬盤(pán),之后的請(qǐng)求會(huì)使用新的 TCP 連接琉预,傳入的 completionHandler 在上述操作完成后執(zhí)行董饰。

- resetWithCompletionHandler:

清空所有的 cookie、緩存圆米、證書(shū)等卒暂,傳入的 completionHandler 在上述操作完成后執(zhí)行。

- (void)getTasksWithCompletionHandler:(void (^)(NSArray<NSURLSessionDataTask *> *dataTasks, NSArray<NSURLSessionUploadTask *> *uploadTasks, NSArray<NSURLSessionDownloadTask *> *downloadTasks))completionHandler;
- (void)getAllTasksWithCompletionHandler:(void (^)(NSArray<__kindof NSURLSessionTask *> *tasks))completionHandler;

獲取 session 中的 task娄帖,在獲取完 task 列表后會(huì)執(zhí)行傳入的 completionHandler 參數(shù)也祠,而 task 列表則作為 block 的參數(shù)傳入。

Delegate

通過(guò) session 的 delegate 可以在請(qǐng)求的整個(gè)生命周期執(zhí)行許多自定義的行為近速。若使用 session 時(shí)不提供 delegate诈嘿,session 對(duì)象則使用一個(gè)系統(tǒng)提供的 delegate堪旧,在這種情況下,創(chuàng)建 task 時(shí)就必須傳入處理回調(diào)的 block 參數(shù)奖亚,否則無(wú)法獲得返回的數(shù)據(jù)了淳梦。

@protocol NSURLSessionDelegate <NSObject>
- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable NSError *)error;
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler;
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session;
@end

@protocol NSURLSessionTaskDelegate <NSURLSessionDelegate>
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest * __nullable))completionHandler;
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler;
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task needNewBodyStream:(void (^)(NSInputStream * __nullable bodyStream))completionHandler;
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend;
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error;
@end

@protocol NSURLSessionDataDelegate <NSURLSessionTaskDelegate>
@optional
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler;
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask;
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didBecomeStreamTask:(NSURLSessionStreamTask *)streamTask;
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data;
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask willCacheResponse:(NSCachedURLResponse *)proposedResponse completionHandler:(void (^)(NSCachedURLResponse * __nullable cachedResponse))completionHandler;
@end

@protocol NSURLSessionDownloadDelegate <NSURLSessionTaskDelegate>
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location;
@optional
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes;
@end

@protocol NSURLSessionStreamDelegate <NSURLSessionTaskDelegate>
@optional
- (void)URLSession:(NSURLSession *)session readClosedForStreamTask:(NSURLSessionStreamTask *)streamTask;
- (void)URLSession:(NSURLSession *)session writeClosedForStreamTask:(NSURLSessionStreamTask *)streamTask;
- (void)URLSession:(NSURLSession *)session betterRouteDiscoveredForStreamTask:(NSURLSessionStreamTask *)streamTask;
- (void)URLSession:(NSURLSession *)session streamTask:(NSURLSessionStreamTask *)streamTask didBecomeInputStream:(NSInputStream *)inputStream outputStream:(NSOutputStream *)outputStream;
@end
  • 當(dāng)在 SSL 握手階段,如果服務(wù)器要求驗(yàn)證客戶端身份或向客戶端提供其證書(shū)用于驗(yàn)證時(shí)昔字,則會(huì)調(diào)用URLSession:didReceiveChallenge:completionHandler:
    URLSession:task:didReceiveChallenge:completionHandler:方法爆袍。傳入的參數(shù)除了對(duì)應(yīng)的 session 和 task,還有NSURLAuthenticationChallenge對(duì)象作郭,它封裝了服務(wù)端對(duì)客戶端的驗(yàn)證請(qǐng)求陨囊,根據(jù)它的 protectionSpace 屬性的
    authenticationMethod,可以知道服務(wù)端要通過(guò)哪種方式驗(yàn)證客戶端或是要求客戶端驗(yàn)證服務(wù)端的證書(shū)夹攒。在代理方法中要執(zhí)行傳入的
    completionHandler Block蜘醋,這個(gè)回調(diào)接收兩個(gè)參數(shù):
    NSURLSessionAuthChallengeDisposition類(lèi)型的 disposition,描述了如何處理驗(yàn)證請(qǐng)求芹助,NSURLCredential對(duì)象堂湖,當(dāng)處理方式需要提供證書(shū)時(shí),傳入該參數(shù)状土。當(dāng) authenticationMethod 的值為:
    NSURLAuthenticationMethodNTLM无蜂、NSURLAuthenticationMethodNegotiate
    NSURLAuthenticationMethodClientCertificate
    NSURLAuthenticationMethodServerTrust時(shí)蒙谓,系統(tǒng)會(huì)先嘗試調(diào)用 session 級(jí)的處理方法斥季,若 session 級(jí)未實(shí)現(xiàn),則嘗試調(diào)用 task 級(jí)的處理方法累驮,而其他情況則是直接調(diào)用 task 級(jí)的處理方法酣倾,無(wú)論 session 級(jí)方法是否實(shí)現(xiàn)。
  • 當(dāng)使用- uploadTaskWithStreamedRequest:方法創(chuàng)建的 task 發(fā)起請(qǐng)求時(shí)谤专,必須實(shí)現(xiàn)代理方法URLSession:task:needNewBodyStream:躁锡,以提供請(qǐng)求需要的 stream。因?yàn)閺妮斎肓髯x數(shù)據(jù)是不可逆的置侍,所以在上傳失敗時(shí)映之,可能會(huì)重新調(diào)用該方法讀取流。在方法中執(zhí)行 block completionHandler 參數(shù)蜡坊,向其傳入
    NSInputStream對(duì)象杠输。
  • 當(dāng)執(zhí)行 upload task 時(shí),系統(tǒng)會(huì)定期的調(diào)用
    URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:方法秕衙,報(bào)告上傳請(qǐng)求體的進(jìn)度蠢甲。
  • 當(dāng)響應(yīng)為重定向到其他請(qǐng)求時(shí),系統(tǒng)會(huì)調(diào)用代理方法
    URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:据忘,在方法中要執(zhí)行 block 參數(shù) completionHandler鹦牛,可向其傳入重定向的新的NSURLRequest對(duì)象搞糕,那么會(huì)正常執(zhí)行重定向請(qǐng)求,也可以傳入 nil能岩,則不執(zhí)行重定向請(qǐng)求并以當(dāng)前響應(yīng)體作為重定向后的響應(yīng)寞宫。
  • 當(dāng)執(zhí)行以方法- downloadTaskWithResumeData:
    - downloadTaskWithResumeData:completionHandler:創(chuàng)建的 download task 時(shí),會(huì)調(diào)用代理方法
    URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:
  • 當(dāng) data task 收到響應(yīng)時(shí)拉鹃,會(huì)調(diào)用代理方法
    URLSession:dataTask:didReceiveResponse:completionHandler:辈赋,在方法中要執(zhí)行 block 參數(shù) completionHandler,向其傳入
    NSURLSessionResponseDisposition枚舉類(lèi)型參數(shù)膏燕,指明繼續(xù)正常返回響應(yīng)體钥屈,還是取消請(qǐng)求,或者將 task 轉(zhuǎn)變?yōu)?download task坝辫。支持
    multipart/x-mixed-replace時(shí)篷就,傳入NSURLSessionResponseBecomeDownload,將 task 轉(zhuǎn)換為 download task 后近忙,會(huì)調(diào)用代理方法
    URLSession:dataTask:didBecomeDownloadTask:
  • 當(dāng)從服務(wù)端接收數(shù)據(jù)時(shí)竭业,系統(tǒng)會(huì)調(diào)用相應(yīng)的代理方法,定期提供已接收到的數(shù)據(jù)及舍,對(duì)于 data task未辆,會(huì)調(diào)用方法URLSession:dataTask:didReceiveData:,而 download task 則會(huì)調(diào)用方法
    URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:
  • 對(duì)于 data task 或 upload task锯玛,在收到所有數(shù)據(jù)后咐柜,可能會(huì)調(diào)用方法
    URLSession:dataTask:willCacheResponse:completionHandler:,提供給應(yīng)用決定是否緩存響應(yīng)的機(jī)會(huì)攘残。方法中要執(zhí)行 block 參數(shù) completionHandler拙友,如果緩存則傳入一個(gè)NSCachedURLResponse對(duì)象,若不想緩存可傳入 nil歼郭。當(dāng)返回的響應(yīng)為緩存中的時(shí)候遗契,則不調(diào)用該方法。
  • 當(dāng) task 執(zhí)行完成后病曾,會(huì)調(diào)用代理方法
    URLSession:task:didCompleteWithError:姊途,如果 task 失敗,error 參數(shù)為包含具體信息的NSError對(duì)象知态,若成功,error 則為 nil立叛。對(duì)于 HTTP 協(xié)議來(lái)說(shuō)负敏,服務(wù)器返回的響應(yīng) code 為失敗時(shí),不屬于 task 執(zhí)行失敗的情況秘蛇,以 task 的角度看其做,這個(gè)請(qǐng)求 task 是成功執(zhí)行的顶考,data 中會(huì)包含返回的內(nèi)容。當(dāng) download task 失敗時(shí)妖泄,在 error 對(duì)象的 userInfo 中可以根據(jù) key
    NSURLSessionDownloadTaskResumeData獲得已下載的數(shù)據(jù)驹沿,之后可用于創(chuàng)建從斷點(diǎn)處繼續(xù)下載的 task。當(dāng) download task 成功執(zhí)行完成后蹈胡,還會(huì)執(zhí)行代理方法URLSession:downloadTask:didFinishDownloadingToURL:渊季,這個(gè)方法是
    NSURLSessionDownloadDelegate協(xié)議中必須實(shí)現(xiàn)的,方法參數(shù)傳入一個(gè)下載文件的臨時(shí)保存路徑罚渐,應(yīng)用需要讀取文件的內(nèi)容或?qū)⑽募频狡渌胤饺春海驗(yàn)榇矸椒▓?zhí)行結(jié)束后,該路徑下的文件會(huì)被刪除荷并,注意合砂,如果讀取文件內(nèi)容的話,則要在單獨(dú)的線程中進(jìn)行源织,否則可能會(huì)造成頁(yè)面卡死翩伪,影響用戶體驗(yàn)。
  • 當(dāng)對(duì) session 對(duì)象執(zhí)行了 invalidate 的相關(guān)方法后谈息,會(huì)調(diào)用代理方法
    URLSession:didBecomeInvalidWithError:缘屹。之后 session 會(huì)釋放對(duì)代理對(duì)象的強(qiáng)引用。

拷貝策略

當(dāng)拷貝一個(gè) session 對(duì)象或 task 對(duì)象時(shí)黎茎,并不會(huì)創(chuàng)建新的實(shí)例囊颅,而是返回該對(duì)象本身。

后臺(tái) session

當(dāng)掛起的應(yīng)用執(zhí)行的后臺(tái)傳輸(下載傅瞻、上傳)完成或者發(fā)生錯(cuò)誤以及需要身份驗(yàn)證時(shí)踢代,系統(tǒng)會(huì)運(yùn)行應(yīng)用并調(diào)用應(yīng)用代理的
- application:handleEventsForBackgroundURLSession:completionHandler:方法。如果傳輸完成可以執(zhí)行一些更新界面的操作嗅骄,如果沒(méi)有成功胳挎,則可以根據(jù) identifier 參數(shù)重新創(chuàng)建 background session 繼續(xù)執(zhí)行。在該方法中應(yīng)使用實(shí)例變量強(qiáng)引用 block 參數(shù) completionHandler溺森,在上述相關(guān)操作(如重新關(guān)聯(lián) session)完成后慕爬,系統(tǒng)會(huì)調(diào)用 session 的代理方法
URLSessionDidFinishEventsForBackgroundURLSession:,此時(shí)在該代理方法中運(yùn)行之前應(yīng)用代理維持的 block屏积,以通知系統(tǒng)應(yīng)用已完成處理工作医窿,要注意的是,該 completionHandler 要在主線程中執(zhí)行炊林。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末姥卢,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌独榴,老刑警劉巖僧叉,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異棺榔,居然都是意外死亡瓶堕,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)症歇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)郎笆,“玉大人,你說(shuō)我怎么就攤上這事当船√饣” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵德频,是天一觀的道長(zhǎng)苍息。 經(jīng)常有香客問(wèn)我,道長(zhǎng)壹置,這世上最難降的妖魔是什么竞思? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮钞护,結(jié)果婚禮上盖喷,老公的妹妹穿的比我還像新娘。我一直安慰自己难咕,他們只是感情好课梳,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著余佃,像睡著了一般暮刃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上爆土,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天椭懊,我揣著相機(jī)與錄音,去河邊找鬼步势。 笑死氧猬,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的坏瘩。 我是一名探鬼主播盅抚,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼倔矾!你這毒婦竟也來(lái)了泉哈?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎丛晦,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體提陶,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡烫沙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了隙笆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锌蓄。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖撑柔,靈堂內(nèi)的尸體忽然破棺而出瘸爽,到底是詐尸還是另有隱情,我是刑警寧澤铅忿,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布剪决,位于F島的核電站,受9級(jí)特大地震影響檀训,放射性物質(zhì)發(fā)生泄漏柑潦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一峻凫、第九天 我趴在偏房一處隱蔽的房頂上張望渗鬼。 院中可真熱鬧,春花似錦荧琼、人聲如沸譬胎。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)堰乔。三九已至,卻和暖如春累舷,著一層夾襖步出監(jiān)牢的瞬間浩考,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工被盈, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留析孽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓只怎,卻偏偏與公主長(zhǎng)得像袜瞬,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子身堡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

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