iOS | NSURLSession 介紹與使用

簡介

NSURLSession 是蘋果公司在2013的 WWDC大會上隨 iOS7 一起發(fā)布的,是 NSURLConnection 的繼任者摘悴。 NSURLConnection在iOS9 之后也被宣布棄用馋嗜。目前 AFNetworking满力、SDWebImage 等知名類庫也都更新使用了 NSURLSession 作喘。

NSURLSession的優(yōu)勢:

  • 針對不同的網(wǎng)絡(luò)請求任務(wù)提供了專門的解決方案厢蒜;
  • 支持任務(wù)取消霞势、暫停、恢復(fù)斑鸦、支持應(yīng)用程序后臺下載愕贡;
  • 安全身份驗(yàn)證方案;
  • 下載操作內(nèi)存優(yōu)化巷屿;
  • 更靈活請求的配置固以。

使用

首先我們看下NSURLSession最簡單的使用,通過下面代碼就可以實(shí)現(xiàn)了基本的網(wǎng)絡(luò)請求了嘱巾。

    NSURL *url = [NSURL URLWithString:@"http://....."];
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *task = [session dataTaskWithURL:url  completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
       // handle  response
    }];
    [task resume];

所有的NSURLSession 網(wǎng)絡(luò)請求基本遵循以下幾個步驟:

  1. 獲取NSURLSession對象
  2. 通過session對象創(chuàng)建 task 任務(wù)
  3. 執(zhí)行 task(task 默認(rèn)是掛起的憨琳,通過resume執(zhí)行)

NSURLSession

NSURLSession繼承NSObject,提供了3種會話模式旬昭,主要通過 NSURLSessionConfiguration來進(jìn)行初始化篙螟,同時還可以設(shè)置 dalegate 來進(jìn)行下載過程監(jiān)聽

+ (NSURLSession *)sharedSession; //共享的會話,該會話使用全局的Cache问拘,Cookie和證書,無法進(jìn)行 Configuration配置
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration; // 通過 NSURLSessionConfiguration初始化
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(nullable id <NSURLSessionDelegate>)delegate delegateQueue:(nullable NSOperationQueue *)queue;  // 通過 NSURLSessionConfiguration遍略、 delegate 、隊(duì)列初始化

接下來我們看下NSURLSessionConfiguration的3種配置骤坐,他們是和NSURLSession的會話模式一一對應(yīng)的

@property (class, readonly, strong) NSURLSessionConfiguration *defaultSessionConfiguration;
@property (class, readonly, strong) NSURLSessionConfiguration *ephemeralSessionConfiguration;
+ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
  • defaultSessionConfiguration 默認(rèn)配置使用的是持久化的硬盤緩存墅冷,存儲證書到用戶鑰匙鏈。存儲cookie到shareCookie或油。
  • ephemeralSessionConfiguration 這個配置中不會對緩存寞忿,Cookie 和證書進(jìn)行持久性的存儲。
  • + backgroundSessionConfigurationWithIdentifier:(NSString *)identifier 它會返回一個后臺 session顶岸∏徽茫可以在應(yīng)用程序掛起,退出或者崩潰的情況下運(yùn)行上傳和下載任務(wù)辖佣。

另外: NSURLSessionConfiguration是提供了很多屬性霹抛,從 指定可用網(wǎng)絡(luò),到 cookie卷谈,安全性杯拐,緩存策略,再到使用自定義協(xié)議,啟動事件的設(shè)置端逼,以及用于移動設(shè)備優(yōu)化的幾個新屬性朗兵,可以找到幾乎任何你想要進(jìn)行配置的選項(xiàng)。

了解了 NSURLSession的模式以及配置顶滩,接下來我們看一下 NSURLSessionTask

NSURLSessionTask

NSURLsessionTask 是一個抽象類余掖,其下有 3 個實(shí)體子類可以直使用用:NSURLSessionDataTaskNSURLSessionUploadTask礁鲁、NSURLSessionDownloadTask盐欺。這 3 個子類封裝了程序三個最基本的網(wǎng)絡(luò)任務(wù):獲取數(shù)據(jù),比如 JSON 或者 XML仅醇,上傳文件和下載文件冗美。

QQ140736@2x.png
  • NSURLSessionDataTask 可以用來處理一般的網(wǎng)絡(luò)請求
  • NSURLSessionDownloadTask 主要用于處理下載請求。
  • NSURLSessionUploadTask 用于處理上傳請求析二。

當(dāng)一個 NSURLSessionDataTask 完成時粉洼,它會帶有相關(guān)聯(lián)的數(shù)據(jù),而一個 NSURLSessionDownloadTask 任務(wù)結(jié)束時甲抖,它會帶回已下載文件的一個臨時的文件路徑。因?yàn)橐话銇碚f心铃,服務(wù)端對于一個上傳任務(wù)的響應(yīng)也會有相關(guān)數(shù)據(jù)返回准谚,所以 NSURLSessionUploadTask 繼承自 NSURLSessionDataTask

所有的task 都是可以取消去扣,暫椭危或者恢復(fù)的。當(dāng)一個 download task 取消時愉棱,可以通過選項(xiàng)來創(chuàng)建一個恢復(fù)數(shù)據(jù)(resume data)唆铐,然后可以傳遞給下一次新創(chuàng)建的 download task,以便繼續(xù)之前的下載奔滑。

不同于直接使用alloc-init 初始化方法艾岂,task 是由一個 NSURLSession 創(chuàng)建的。每個 task 的構(gòu)造方法都對應(yīng)有或者沒有 completionHandler block 的兩個版本朋其。如果 使用completionHandlerblock王浴,代理回調(diào)將不會執(zhí)行。

NSURLSessionTask工廠方法

NSURLSessionTask的工廠方法可以根據(jù)我們不同的需求返回不同的 task梅猿,這些task 不會立即運(yùn)行氓辣,允許我們進(jìn)一步的配置,然后可以使用 resume 方法來讓它開始運(yùn)行袱蚓。

Datatask 可以通過 NSURLNSURLRequest 創(chuàng)建

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];

Uploadtask 的創(chuàng)建需要使用一個 request钞啸,另外加上一個要上傳的 NSData 對象或者是一個本地文件的路徑對應(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 也需要一個 request或者Url,不同之處在于 completionHandler 這個 block。Datataskuploadtask 會在任務(wù)完成時一次性返回体斩,但是 Download task是將數(shù)據(jù)一點(diǎn)點(diǎn)地寫入本地的臨時文件梭稚。所以在 completionHandler 這個 block 里,我們需要把文件從一個臨時地址移動到一個永久的地址保存起來:

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];

上面介紹了幾種 NSURLSessionTask 的基本使用硕勿,都是通過completionHandler這個 block 來進(jìn)行任務(wù)處理回調(diào)的哨毁,下來我們看看他的代理都有哪些,以及使用

NSURLSession代理

在我們請求過程中源武,如果想要監(jiān)聽網(wǎng)絡(luò)操作過程中發(fā)生的事件扼褪,比如我們下載一個大文件的時候,如果要等到下載完成可能會需要比較長的事件粱栖,這時候更好的體驗(yàn)是能夠提供一個下載進(jìn)度话浇。類似這樣的事件我們就需要用到代理。

我們在使用三種 task 的任意一種的時候都可以指定相應(yīng)的代理闹究。NSURLSession 的代理對象結(jié)構(gòu)如下:


QQ140750@2x.png
  • NSURLSessionDelegate 作為所有代理的基類幔崖,定義了網(wǎng)絡(luò)請求最基礎(chǔ)的代理方法。
  • NSURLSessionTaskDelegate - 定義了網(wǎng)絡(luò)請求任務(wù)相關(guān)的代理方法渣淤。
  • NSURLSessionDownloadDelegate - 用于下載任務(wù)相關(guān)的代理方法赏寇,比如下載進(jìn)度等等。
  • NSURLSessionDataDelegate - 用于普通數(shù)據(jù)任務(wù)和上傳任務(wù)价认。

下面以下載為例嗅定,我們看下代碼如何實(shí)現(xiàn)的

- (void)downloadtask{
    
    //  服務(wù)器地址
    NSURL *url = [NSURL URLWithString:@"http://d1.music.126.net/dmusic/NeteaseMusic_1.5.10_632_web.dmg"];
    //  創(chuàng)建 SessionConfiguration配置
    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    //  創(chuàng)建session實(shí)例并設(shè)置代理,用于監(jiān)聽下載
    NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
    //  創(chuàng)建 task
    self.task = [session downloadTaskWithURL:url];
    // 開始執(zhí)行
    [self.task resume];
}

#pragma -mark NSURLSessionDownloadDelegate

/* 當(dāng)下載任務(wù)完成下載時調(diào)用*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                              didFinishDownloadingToURL:(NSURL *)location{
    
    // location是一個temp文件下的臨時路徑,自己需要保存
    NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
    [[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:filePath] error:nil];
}

/* 定期發(fā)送通知委托下載進(jìn)度. */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                                           didWriteData:(int64_t)bytesWritten
                                      totalBytesWritten:(int64_t)totalBytesWritten
                              totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
    
    // 可在這里通過已寫入的長度和總長度算出下載進(jìn)度
    CGFloat progress = 1.0 * totalBytesWritten / totalBytesExpectedToWrite;
    NSLog(@"%f",progress);
    
}

/* 當(dāng)下載已恢復(fù)時發(fā)送 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                                      didResumeAtOffset:(int64_t)fileOffset
                                     expectedTotalBytes:(int64_t)expectedTotalBytes{
}

/* 任務(wù)完成調(diào)用,查看是否成功 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{

    if (!error){
        NSLog(@"下載完成");
    }else{
        NSLog(@"下載失敗");
    }
}

通過實(shí)現(xiàn)NSURLSessionDownloadDelegate 協(xié)議,就可以實(shí)現(xiàn)接收下載完成的通知用踩,下載進(jìn)度變化的通知渠退,以及下載進(jìn)度恢復(fù)的通知。

總結(jié)

NSURLSession 除了我們介紹的支持 task 特性脐彩,NSURLSessionConfiguration 配置對象碎乃,以及代理之外還提供了很多關(guān)于網(wǎng)絡(luò)請求的相關(guān)特性,比如緩存控制惠奸,Cookie 控制梅誓,HTTP 驗(yàn)證操作等等》鹉希總之 NSURLSession 簡單的接口之外证九,也提供了強(qiáng)大的體系。

NSURLSession 相比 AFN這些第三方庫來說也有一些不足共虑,比如它沒有提供很方便的自動數(shù)據(jù)類型轉(zhuǎn)換愧怜。比如,AFN 中可以自動將服務(wù)端返回的 JSON 數(shù)據(jù)識別并解析出來妈拌,而使用 NSURLSession 則需要自己來完成拥坛。

后續(xù)有時間我會繼續(xù)分析一下 NSURLSession在 AFN 中的使用蓬蝶!

參考鏈接:
https://developer.apple.com/documentation/foundation/nsurlsession
https://swiftcafe.io/2015/12/20/nsurlsession
http://www.cocoachina.com/ios/20180108/21778.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市猜惋,隨后出現(xiàn)的幾起案子丸氛,更是在濱河造成了極大的恐慌,老刑警劉巖著摔,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缓窜,死亡現(xiàn)場離奇詭異,居然都是意外死亡谍咆,警方通過查閱死者的電腦和手機(jī)禾锤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來摹察,“玉大人恩掷,你說我怎么就攤上這事」┖浚” “怎么了黄娘?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長克滴。 經(jīng)常有香客問我逼争,道長,這世上最難降的妖魔是什么劝赔? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任誓焦,我火速辦了婚禮,結(jié)果婚禮上望忆,老公的妹妹穿的比我還像新娘罩阵。我一直安慰自己竿秆,他們只是感情好启摄,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著幽钢,像睡著了一般歉备。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上匪燕,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天蕾羊,我揣著相機(jī)與錄音,去河邊找鬼帽驯。 笑死龟再,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的尼变。 我是一名探鬼主播利凑,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼浆劲,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了哀澈?” 一聲冷哼從身側(cè)響起牌借,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎割按,沒想到半個月后膨报,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡适荣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年现柠,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片束凑。...
    茶點(diǎn)故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡晒旅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出汪诉,到底是詐尸還是另有隱情废恋,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布扒寄,位于F島的核電站鱼鼓,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏该编。R本人自食惡果不足惜迄本,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望课竣。 院中可真熱鬧嘉赎,春花似錦、人聲如沸于樟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽迂曲。三九已至靶橱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間路捧,已是汗流浹背关霸。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留杰扫,地道東北人队寇。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像章姓,于是被迫代替她去往敵國和親佳遣。 傳聞我的和親對象是個殘疾皇子炭序,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評論 2 348

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