iOS NSURLSession使用詳解

一秃殉、整體介紹

  • NSURLSession在2013年隨著iOS7的發(fā)布一起面世,蘋果對它的定位是作為NSURLConnection的替代者,然后逐步將NSURLConnection退出歷史舞臺。現(xiàn)在使用最廣泛的第三方網(wǎng)絡(luò)框架:AFNetworking锐峭、SDWebImage等等都使用了NSURLSession。作為iOS開發(fā)人員可婶,應(yīng)該緊隨蘋果的步伐沿癞,不斷的學(xué)習(xí),無論是軟件的更新矛渴、系統(tǒng)的更新抛寝、API的更新,而不能墨守成規(guī)。

  • Session翻譯為中文意思是會話盗舰,我們知道晶府,在七層網(wǎng)絡(luò)協(xié)議中有物理層->數(shù)據(jù)鏈路層->網(wǎng)絡(luò)層->傳輸層->會話層->表示層->應(yīng)用層,那我們可以將NSURLSession類理解為會話層钻趋,用于管理網(wǎng)絡(luò)接口的創(chuàng)建川陆、維護、刪除等等工作蛮位,我們要做的工作也只是會話層之后的層即可较沪,底層的工作NSURLSession已經(jīng)幫我們封裝好了。

  • image
  • 另外還有一些Session失仁,比如AVAudioSession用于音視頻訪問尸曼,WCSession用于WatchOS通訊,它們都是建立一個會話萄焦,并管理會話控轿,封裝一些底層,方便我們使用拂封。舉一反三茬射。

二、使用的一般步驟

其核心就是對網(wǎng)絡(luò)任務(wù)進行封裝冒签,實現(xiàn)多線程在抛。比如將一個網(wǎng)絡(luò)請求交給NSURLSession,最后NSURLSession將訪問結(jié)果通過block回調(diào)返回萧恕,期間自動實現(xiàn)多線程刚梭,而且可以通過代理實現(xiàn)監(jiān)聽(是否成功,當(dāng)前的進度等等)票唆; 大致分為3個步驟:

1 NSURL:請求地址望浩,定義一個網(wǎng)絡(luò)資源路徑:

NSURL *url = [NSURL URLWithString:@"協(xié)議://主機地址/路徑?參數(shù)&參數(shù)"];

解釋如下:

  • 協(xié)議:不同的協(xié)議,代表著不同的資源查找方式惰说、資源傳輸方式,比如常用的http缘回,ftp等
  • 主機地址:存放資源的主機的IP地址(域名)
  • 路徑:資源在主機中的具體位置
  • 參數(shù):參數(shù)可有可無吆视,也可以多個。如果帶參數(shù)的話酥宴,用“?”號后面接參數(shù)啦吧,多個參數(shù)的話之間用&隔開

2 NSURLRequest:請求,根據(jù)前面的NSURL建立一個請求:

NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];

參數(shù)解釋如下:

  • url:資源路徑
  • cachePolicy:緩存策略(無論使用哪種緩存策略拙寡,都會在本地緩存數(shù)據(jù))授滓,類型為美劇類型,取值如下:
    *   NSURLRequestUseProtocolCachePolicy = 0 //默認(rèn)的緩存策略,使用協(xié)議的緩存策略
    *   NSURLRequestReloadIgnoringLocalCacheData = 1 //每次都從網(wǎng)絡(luò)加載
    *   NSURLRequestReturnCacheDataElseLoad = 2 //返回緩存否則加載般堆,**很少使用**
    *   NSURLRequestReturnCacheDataDontLoad = 3 //只返回緩存在孝,沒有也不加載,**很少使用**
  • timeoutInterval:超時時長淮摔,默認(rèn)60s私沮,這里設(shè)置為30s

另外,還可以設(shè)置其它一些信息和橙,比如請求頭仔燕,請求體等等,如下:

注意魔招,下面的request應(yīng)為NSMutableURLRequest晰搀,即可變類型

// 告訴服務(wù)器數(shù)據(jù)為json類型
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; // 設(shè)置請求體(json類型)
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:@{@"userid":@"123456"} options:NSJSONWritingPrettyPrinted error:nil];
request.HTTPBody = jsonData; 

3 NSURLSession:創(chuàng)建NSURLSession發(fā)送請求

  • 為了方便使用,蘋果提供了一個全局的NSURLSession單例办斑,如同NSURLConnection一樣外恕。這樣做的缺陷就是不能監(jiān)控,如果想要監(jiān)控每一個請求俄周,則必須通過代理來監(jiān)聽吁讨,我們知道單例是一對多的,而代理是一對一峦朗,因此必須自己實例化單獨的Session任務(wù)對象(NSURLConnection則很難)建丧,來實現(xiàn)單獨監(jiān)控。
  • 系統(tǒng)一共提供了5種任務(wù)類波势,繼承關(guān)系如下圖所示翎朱。其中NSURLSessionTask為抽象類,不能實現(xiàn)網(wǎng)絡(luò)訪問尺铣,NSURLSessionStreanTask(以流的方式進行網(wǎng)絡(luò)訪問)使用的比較少.使用的多的是dataTask拴曲、downloadTask、uploadTask凛忿,即圖中紅色框框圈的部分澈灼,基本滿足了網(wǎng)絡(luò)訪問的基本需求:獲取數(shù)據(jù)(通常是JSON、XML等)店溢、文件上傳叁熔、文件下載。這三個類都是NSURLSessionTask這個抽象類的子類床牧,相比直接使用NSURLConnection,NSURLSessionTask支持任務(wù)的暫停荣回、取消和恢復(fù),并且默認(rèn)任務(wù)運行在其他非主線程中戈咳。
  • 根據(jù)圖中代理協(xié)議的名字不難發(fā)現(xiàn)心软,每一個任務(wù)類都有相對應(yīng)的代理協(xié)議壕吹,只有NSURLSessionUploadTask沒有對應(yīng)的代理協(xié)議,因為NSURLSessionUploadTask繼承自NSURLSessionDataTask删铃,因此NSURLSessionDataDelegate即為NSURLSessionUploadTask對應(yīng)的代理協(xié)議耳贬。
image
image

三 舉例

1.NSURLSession請求網(wǎng)絡(luò)數(shù)據(jù)

下面以蘋果提供的全局NSURLSession單例為例,代碼如下:

/// 向網(wǎng)絡(luò)請求數(shù)據(jù)
- (void)NSURLSessionTest {
    // 1.創(chuàng)建url
    // 請求一個網(wǎng)頁
    NSString *urlString = @"http://www.cnblogs.com/mddblog/p/5215453.html";

// 一些特殊字符編碼
    urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
    NSURL *url = [NSURL URLWithString:urlString];
    
    // 2.創(chuàng)建請求 并:設(shè)置緩存策略為每次都從網(wǎng)絡(luò)加載 超時時間30秒
    NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:30];

    // 3.采用蘋果提供的共享session
    NSURLSession *sharedSession = [NSURLSession sharedSession];
    
    // 4.由系統(tǒng)直接返回一個dataTask任務(wù)
    NSURLSessionDataTask *dataTask = [sharedSession dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        // 網(wǎng)絡(luò)請求完成之后就會執(zhí)行泳姐,NSURLSession自動實現(xiàn)多線程
        NSLog(@"%@",[NSThread currentThread]);
        if (data && (error == nil)) {
            // 網(wǎng)絡(luò)訪問成功
            NSLog(@"data=%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
        } else {
            // 網(wǎng)絡(luò)訪問失敗
            NSLog(@"error=%@",error);
        }
    }];
    
    // 5.每一個任務(wù)默認(rèn)都是掛起的效拭,需要調(diào)用 resume 方法
    [dataTask resume];
}

2.NSURLSession文件下載

/// 文件下載
- (void)NSURLSessionDownloadTaskTest { // 1.創(chuàng)建url
  NSString *urlString = [NSString stringWithFormat:@"http://localhost/周杰倫 - 楓.mp3"]; // 一些特殊字符編碼
  urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
  NSURL *url = [NSURL URLWithString:urlString]; // 2.創(chuàng)建請求
  NSURLRequest *request = [NSURLRequest requestWithURL:url]; // 3.創(chuàng)建會話,采用蘋果提供全局的共享session
  NSURLSession *sharedSession = [NSURLSession sharedSession]; // 4.創(chuàng)建任務(wù)
  NSURLSessionDownloadTask *downloadTask = [sharedSession downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error == nil) { // location:下載任務(wù)完成之后,文件存儲的位置胖秒,這個路徑默認(rèn)是在tmp文件夾下! // 只會臨時保存缎患,因此需要將其另存
          NSLog(@"location:%@",location.path); // 采用模擬器測試,為了方便將其下載到Mac桌面 // NSString *filePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
          NSString *filePath = @"/Users/userName/Desktop/周杰倫 - 楓.mp3";
          NSError *fileError;
          [[NSFileManager defaultManager] copyItemAtPath:location.path toPath:filePath error:&fileError]; if (fileError == nil) {
              NSLog(@"file save success");
          } else {
              NSLog(@"file save error: %@",fileError);
          }
      } else {
          NSLog(@"download error:%@",error);
      }
  }]; // 5.開啟任務(wù)
[downloadTask resume];
}

3.NSURLSession文件上傳

3.1 采用uploadTask任務(wù)阎肝,以數(shù)據(jù)流的方式進行上傳
這種方式好處就是大小不受限制挤渔,上傳需要服務(wù)器端腳本支持,腳本源代碼見本文檔最后的附錄风题,客戶端示例代碼如下:

/// 以流的方式上傳判导,大小理論上不受限制,但應(yīng)注意時間
- (void) NSURLSessionBinaryUploadTaskTest { // 1.創(chuàng)建url  采用Apache本地服務(wù)器
    NSString *urlString = @"http://localhost/upload.php"; urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];
    NSURL *url = [NSURL URLWithString:urlString]; // 2.創(chuàng)建請求
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; // 文件上傳使用post
    request.HTTPMethod = @"POST"; // 3.開始上傳   request的body data將被忽略沛硅,而由fromData提供
    [[[NSURLSession sharedSession] uploadTaskWithRequest:request fromData:[NSData dataWithContentsOfFile:@"/Users/userName/Desktop/IMG_0359.jpg"]     completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error == nil) {
            NSLog(@"upload success:%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
        } else {
            NSLog(@"upload error:%@",error);
        }
    }] resume];
}

3.2 采用dataTask任務(wù)眼刃,拼接表單的方式進行上傳

  • 上傳的關(guān)鍵是請求體部分的表單拼接,獲取本地上傳文件的類型(MIME Types)摇肌,至于具體的網(wǎng)絡(luò)上傳則很簡單擂红。 另外拼接表單的方式會有大小限制,即HTML的MAX_FILE_SIZE限制(可以自己設(shè)定围小,一般2MB)昵骤。

  • 根據(jù)上面的繼承關(guān)系圖,我們知道uploadTask是dataTask的子類肯适,也可以使用uploadTask來代替dataTask变秦。在代碼示例中4.2步驟完全可以替換4.1步驟。這時框舔,uploadTaskWithRequest函數(shù)的fromData可有可無蹦玫,文件已在request里面包含。

注意:然而在蘋果官方對uploadTaskWithRequest函數(shù)的介紹:request的body data in this request object are ignored刘绣,會被忽略樱溉,而測試時發(fā)現(xiàn)沒有被忽略,且request必須包含HTTPBody额港,反而fromData被忽略。那么暫時理解為蘋果對uploadTaskWithRequest函數(shù)的使用時沒有考慮拼接表單的方式歧焦,那么當(dāng)我們使用拼接表單時移斩,建議不要使用uploadTask肚医,雖然這樣也能成功

  • 服務(wù)器端用到的upload.php源代碼見本文最后的附錄

表單拼接格式如下,boundary作為分界線:

--boundary
Content-Disposition:form-data;name=”表單控件名稱”;filename=”上傳文件名稱”
Content-Type:要上傳文件MIME Types

要上傳文件二進制數(shù)據(jù); --boundary--

拼接表單示例代碼:

/// 文件上傳
- (void)NSURLSessionUploadTaskTest { // 1.創(chuàng)建url  采用Apache本地服務(wù)器
    NSString *urlString = @"http://localhost/upload/upload.php";
    urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];
    NSURL *url = [NSURL URLWithString:urlString]; // 2.創(chuàng)建請求
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; // 文件上傳使用post
    request.HTTPMethod = @"POST";
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",@"boundary"];
    [request setValue:contentType forHTTPHeaderField:@"Content-Type"]; // 3.拼接表單向瓷,大小受MAX_FILE_SIZE限制(2MB)  FilePath:要上傳的本地文件路徑  formName:表單控件名稱肠套,應(yīng)于服務(wù)器一致
    NSData* data = [self getHttpBodyWithFilePath:@"/Users/userName/Desktop/IMG_0359.jpg" formName:@"file" reName:@"newName.png"];
    request.HTTPBody = data; // 根據(jù)需要是否提供,非必須,如果不提供猖任,session會自動計算
    [request setValue:[NSString stringWithFormat:@"%lu",data.length] forHTTPHeaderField:@"Content-Length"]; // 4.1 使用dataTask
    [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error == nil) {
            NSLog(@"upload success:%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
        } else {
            NSLog(@"upload error:%@",error);
        }

    }] resume]; #if 0
    // 4.2 開始上傳 使用uploadTask   fromData:可有可無你稚,會被忽略
    [[[NSURLSession sharedSession] uploadTaskWithRequest:request fromData:nil     completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error == nil) {
            NSLog(@"upload success:%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
        } else {
            NSLog(@"upload error:%@",error);
        }
    }] resume]; #endif } /// filePath:要上傳的文件路徑   formName:表單控件名稱  reName:上傳后文件名
- (NSData *)getHttpBodyWithFilePath:(NSString *)filePath formName:(NSString *)formName reName:(NSString *)reName
{
    NSMutableData *data = [NSMutableData data];
    NSURLResponse *response = [self getLocalFileResponse:filePath]; // 文件類型:MIMEType  文件的大小:expectedContentLength  文件名字:suggestedFilename
    NSString *fileType = response.MIMEType; // 如果沒有傳入上傳后文件名稱,采用本地文件名!
    if (reName == nil) {
        reName = response.suggestedFilename;
    } // 表單拼接
    NSMutableString *headerStrM =[NSMutableString string];
    [headerStrM appendFormat:@"--%@\r\n",@"boundary"]; // name:表單控件名稱  filename:上傳文件名
    [headerStrM appendFormat:@"Content-Disposition: form-data; name=%@; filename=%@\r\n",formName,reName];
    [headerStrM appendFormat:@"Content-Type: %@\r\n\r\n",fileType];
    [data appendData:[headerStrM dataUsingEncoding:NSUTF8StringEncoding]]; // 文件內(nèi)容
    NSData *fileData = [NSData dataWithContentsOfFile:filePath];
    [data appendData:fileData];

    NSMutableString *footerStrM = [NSMutableString stringWithFormat:@"\r\n--%@--\r\n",@"boundary"];
    [data appendData:[footerStrM  dataUsingEncoding:NSUTF8StringEncoding]]; // NSLog(@"dataStr=%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    return data;
} /// 獲取響應(yīng)朱躺,主要是文件類型和文件名
- (NSURLResponse *)getLocalFileResponse:(NSString *)urlString
{
    urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]]; // 本地文件請求
    NSURL *url = [NSURL fileURLWithPath:urlString];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    __block NSURLResponse *localResponse = nil; // 使用信號量實現(xiàn)NSURLSession同步請求
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        localResponse = response;
        dispatch_semaphore_signal(semaphore);
    }] resume];
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); return localResponse;
}

四 NSURLSessionConfiguration


NSURLConnection是全局性的刁赖,即它的配置對全局有效,如果有兩個鏈接需要不同的cookies长搀、證書這些公共資源宇弛,則NSURLConnection無法滿足要求,這時NSURLSession的優(yōu)勢則體現(xiàn)出來源请,NSURLSession可以同過NSURLSessionConfiguration可以設(shè)置全局的網(wǎng)絡(luò)訪問屬性枪芒。

NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; // delegateQueue:請求完成回調(diào)函數(shù)和代理函數(shù)的運行線程,如果為nil則系統(tǒng)自動創(chuàng)建一個串行隊列谁尸,不影響sessionTask的運行線程
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];

三種會話方式:

  1. defaultSessionConfiguration:進程內(nèi)會話(默認(rèn)會話)舅踪,類似 NSURLConnection的標(biāo)準(zhǔn)配置,用硬盤來緩存數(shù)據(jù)良蛮。
  2. ephemeralSessionConfiguration:臨時的進程內(nèi)會話(內(nèi)存)抽碌,不會將cookie、緩存儲存到本地背镇,只會放到內(nèi)存中咬展,當(dāng)應(yīng)用程序退出后數(shù)據(jù)也會消失,可以用于實現(xiàn)“秘密瀏覽”
  3. backgroundSessionConfiguration:建立后臺會話可以在應(yīng)用程序掛起,退出瞒斩,崩潰的情況下運行上傳和下載任務(wù)破婆,后臺另起一個線程。另外胸囱,系統(tǒng)會根據(jù)設(shè)備的負(fù)載程度決定分配下載的資源祷舀,因此有可能會很慢甚至超時失敗。

設(shè)置一些網(wǎng)絡(luò)屬性:

  • HTTPAdditionalHeaders:可以設(shè)置出站請求的數(shù)據(jù)頭
configuration.HTTPAdditionalHeaders = @{ @"Accept": 
@"application/json", 
@"Accept-Language": 
@"en", 
@"Authorization": authString, 
@"User-Agent": userAgentString};
  • networkServiceType烹笔,設(shè)置網(wǎng)絡(luò)服務(wù)類型

    • NSURLNetworkServiceTypeDefault 默認(rèn)
    • NSURLNetworkServiceTypeVoIP VoIP
    • NSURLNetworkServiceTypeVideo 視頻
    • NSURLNetworkServiceTypeBackground 后臺
    • NSURLNetworkServiceTypeVoice 語音
  • allowsCellularAccess:允許蜂窩訪問

  • timeoutIntervalForRequest:請求的超時時長

  • requestCachePolicy:緩存策略

注意事項:如果是自定義會話并指定了代理裳扯,會話會對代理進行強引用,在視圖控制器銷毀之前,需要取消網(wǎng)絡(luò)會話谤职,否則會造成內(nèi)存泄漏

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末饰豺,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子允蜈,更是在濱河造成了極大的恐慌冤吨,老刑警劉巖蒿柳,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異漩蟆,居然都是意外死亡垒探,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門怠李,熙熙樓的掌柜王于貴愁眉苦臉地迎上來圾叼,“玉大人,你說我怎么就攤上這事捺癞∫奈茫” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵翘簇,是天一觀的道長撬码。 經(jīng)常有香客問我,道長版保,這世上最難降的妖魔是什么呜笑? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮彻犁,結(jié)果婚禮上叫胁,老公的妹妹穿的比我還像新娘。我一直安慰自己汞幢,他們只是感情好驼鹅,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著森篷,像睡著了一般输钩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仲智,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天买乃,我揣著相機與錄音,去河邊找鬼钓辆。 笑死剪验,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的前联。 我是一名探鬼主播功戚,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼似嗤!你這毒婦竟也來了啸臀?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤烁落,失蹤者是張志新(化名)和其女友劉穎乘粒,沒想到半個月后席揽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡谓厘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了寸谜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片竟稳。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖熊痴,靈堂內(nèi)的尸體忽然破棺而出他爸,到底是詐尸還是另有隱情,我是刑警寧澤果善,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布诊笤,位于F島的核電站,受9級特大地震影響巾陕,放射性物質(zhì)發(fā)生泄漏讨跟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一鄙煤、第九天 我趴在偏房一處隱蔽的房頂上張望晾匠。 院中可真熱鬧,春花似錦梯刚、人聲如沸凉馆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽澜共。三九已至,卻和暖如春锥腻,著一層夾襖步出監(jiān)牢的瞬間嗦董,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工旷太, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留展懈,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓供璧,卻偏偏與公主長得像存崖,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子睡毒,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

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