SDWebImage學(xué)習(xí)筆記之NSURLSession

NSURLSession概述

NSURLSession是從iOS7開(kāi)始使用敦姻,用于替代NSURLConnection進(jìn)行網(wǎng)絡(luò)數(shù)據(jù)傳輸?shù)念?lèi)瘾境。著名的AFNetworking庫(kù)的2.0版本采用的NSURLConnection,但是從3.0版本開(kāi)始镰惦,已經(jīng)用NSURLSession替換了NSURLConnection迷守。

NSURLSession可以與delegate(代理)綁定,在一個(gè)會(huì)話的生命周期內(nèi)旺入,delegate會(huì)被某些事件調(diào)用兑凿,例如服務(wù)端認(rèn)證或者確定加載的資源是否應(yīng)該轉(zhuǎn)化為下載。

NSURLSession實(shí)例是線程安全的茵瘾,它會(huì)創(chuàng)建NSURLSessionTask對(duì)象來(lái)執(zhí)行數(shù)據(jù)的加載礼华。被創(chuàng)建的NSURLSessionTask對(duì)象初始化狀態(tài)是suspend(掛起),需要調(diào)用resume(恢復(fù))方法來(lái)執(zhí)行拗秘。


NSURLSessionTask

NSURLSessionTask有四個(gè)子類(lèi):NSURLSessionDataTask圣絮、NSURLSessionUploadTask和NSURLSessionDownloadTask,NSURLSessionStreamTask雕旨。

  1. NSURLSessionDataTask用于執(zhí)行普通的任務(wù)扮匠,例如請(qǐng)求或上傳數(shù)據(jù)。
  2. NSURLSessionUploadTask繼承自NSURLSessionUploadTask用于上傳文件或數(shù)據(jù)到服務(wù)器凡涩。
  3. NSURLSessionDownloadTask會(huì)直接將響應(yīng)數(shù)據(jù)寫(xiě)入臨時(shí)文件棒搜,默認(rèn)下載到沙盒的temp目錄下。下載完成后活箕,delegate會(huì)接收到URLSession:downloadTask:didFinishDownloadingToURL: 消息力麸。
  4. NSURLSessionStreamTask用于建立一個(gè) TCP/IP 連接,自iOS9以后開(kāi)始使用育韩。

NSURLSessionConfiguration

NSURLSessionConfiguration是NSURLSession的配置類(lèi)克蚂,用于生成NSURLSession對(duì)象。
NSURLSessionConfiguration有三種初始化方式:

  1. defaultSessionConfiguration座慰。返回的全局會(huì)話使用磁盤(pán)來(lái)緩存credential, cache and cookie陨舱。
  2. ephemeralSessionConfiguration。返回的臨時(shí)會(huì)話使用內(nèi)存而不使用磁盤(pán)來(lái)緩存credential, cache and cookie版仔,app一旦退出,數(shù)據(jù)會(huì)被清空。
  3. backgroundSessionConfiguration蛮粮。返回的后臺(tái)
    會(huì)話可以在app被掛起時(shí)執(zhí)行網(wǎng)絡(luò)操作益缎,但必須要傳入一個(gè)NSString類(lèi)型的identifier。

NSURLSession使用

NSURLSession提供了兩種方法來(lái)創(chuàng)建會(huì)話:

+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(nullable id <NSURLSessionDelegate>)delegate delegateQueue:(nullable NSOperationQueue *)queue;

第二個(gè)方法可以傳入delegate來(lái)監(jiān)聽(tīng)會(huì)話事件然想,delegate需要遵循NSURLSessionDelegate協(xié)議且會(huì)被強(qiáng)引用莺奔,還可以傳入NSOperationQueue對(duì)象來(lái)指定delegate在哪個(gè)隊(duì)列被調(diào)用,傳入值為nil時(shí)变泄,session會(huì)默認(rèn)創(chuàng)建一個(gè)串行隊(duì)列來(lái)執(zhí)行delegate的方法令哟。

創(chuàng)建完會(huì)話之后,需要?jiǎng)?chuàng)建一個(gè)任務(wù)來(lái)執(zhí)行具體的網(wǎng)絡(luò)傳輸操作妨蛹。

// NSURLSessionDataTask
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request;
- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url;

// NSURLSessionUploadTask
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL;
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData;
- (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request;

// NSURLSessionDownloadTask
- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request;
- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url;
- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData;

// NSURLSessionStreamTask
- (NSURLSessionStreamTask *)streamTaskWithHostName:(NSString *)hostname port:(NSInteger)port API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) __WATCHOS_PROHIBITED;
- (NSURLSessionStreamTask *)streamTaskWithNetService:(NSNetService *)service API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) __WATCHOS_PROHIBITED;
普通任務(wù)獲取資訊列表:
// 配置URL
NSURL *url = [NSURL URLWithString:@"http://toutiao-ali.juheapi.com/toutiao/index"];
// 配置URLRequest
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setValue:@"APPCODE fd4e0a674e274e46ad3e26ab508ff21c" forHTTPHeaderField:@"Authorization"];
// 配置全局會(huì)話
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
// 返回掛起的普通任務(wù)
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    // 解析數(shù)據(jù)
    NSString *string = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"%@", string);
}];
// 恢復(fù)普通任務(wù)
[dataTask resume];

執(zhí)行resume方法后任務(wù)才會(huì)開(kāi)始加載數(shù)據(jù)屏富,并在回調(diào)中返回響應(yīng),不然task永遠(yuǎn)是掛起狀態(tài)蛙卤。

下載任務(wù)下載圖片資源:
// 配置URL
NSURL *url = [NSURL URLWithString:@"https://image.baidu.com/search/down?tn=download&word=download&ie=utf8&fr=detail&url=https%3A%2F%2Ftimgsa.baidu.com%2Ftimg%3Fimage%26quality%3D80%26size%3Db9999_10000%26sec%3D1530781485542%26di%3Dde29981bb7d210737be1a7da40acd236%26imgtype%3D0%26src%3Dhttp%253A%252F%252Fimg.sccnn.com%252Fbimg%252F338%252F27244.jpg&thumburl=https%3A%2F%2Fss1.bdstatic.com%2F70cFuXSh_Q1YnxGkpoWK1HF6hhy%2Fit%2Fu%3D4194403647%2C3630027324%26fm%3D27%26gp%3D0.jpg"];
// 配置全局會(huì)話
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];
// 返回掛起的下載任務(wù)
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    // 返回沙盒tmp目錄的臨時(shí)文件
    NSLog(@"%@", location);
}];
// 恢復(fù)下載任務(wù)
[downloadTask resume];
通過(guò)代理方法實(shí)現(xiàn)數(shù)據(jù)加載
// 配置URL
NSURL *url = [NSURL URLWithString:@"https://image.baidu.com/search/down?tn=download&word=download&ie=utf8&fr=detail&url=https%3A%2F%2Ftimgsa.baidu.com%2Ftimg%3Fimage%26quality%3D80%26size%3Db9999_10000%26sec%3D1530781485542%26di%3Dde29981bb7d210737be1a7da40acd236%26imgtype%3D0%26src%3Dhttp%253A%252F%252Fimg.sccnn.com%252Fbimg%252F338%252F27244.jpg&thumburl=https%3A%2F%2Fss1.bdstatic.com%2F70cFuXSh_Q1YnxGkpoWK1HF6hhy%2Fit%2Fu%3D4194403647%2C3630027324%26fm%3D27%26gp%3D0.jpg"];
// 配置全局會(huì)話
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
// 傳入代理對(duì)象
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];
// 返回掛起的普通任務(wù)狠半,不用completionHandler返回?cái)?shù)據(jù)
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url];
// 恢復(fù)下載任務(wù)
[dataTask resume];

會(huì)話初始化時(shí)將self作為代理對(duì)象傳入,代理對(duì)象需要遵循NSURLSessionDataDelegate協(xié)議和NSURLSessionTaskDelegate協(xié)議颤难,任務(wù)在執(zhí)行過(guò)程中通知代理對(duì)象具體的執(zhí)行步驟神年。

#pragma mark NSURLSessionDataDelegate

/**
 任務(wù)收到服務(wù)器的初始響應(yīng)

 @param session 用戶創(chuàng)建的會(huì)話
 @param dataTask 用戶創(chuàng)建的數(shù)據(jù)任務(wù)
 @param response 服務(wù)器響應(yīng)
 @param completionHandler 回調(diào),告知系統(tǒng)是否繼續(xù)傳輸
 */
- (void)URLSession:(NSURLSession *)session
          dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
{
    // 是否允許繼續(xù)傳輸數(shù)據(jù)
    NSURLSessionResponseDisposition disposition = NSURLSessionResponseAllow;
    // 響應(yīng)內(nèi)容的預(yù)期長(zhǎng)度行嗤,若預(yù)期長(zhǎng)度未知已日,返回-1
    NSInteger expected = (NSInteger)response.expectedContentLength;
    expected = expected > 0 ? expected : 0;
    // 不執(zhí)行此行代碼,默認(rèn)取消傳輸
    completionHandler(disposition);
}

/**
 任務(wù)收到服務(wù)器返回的數(shù)據(jù)(可能多次調(diào)用)

 @param session 用戶創(chuàng)建的會(huì)話
 @param dataTask 用戶創(chuàng)建的數(shù)據(jù)任務(wù)
 @param data 當(dāng)次返回的數(shù)據(jù)
 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
    if (!self.jjData) {
        self.jjData = [[NSMutableData alloc] init];
    }
    // 拼接當(dāng)次返回的數(shù)據(jù)
    [self.jjData appendData:data];
    // 計(jì)算當(dāng)前總數(shù)據(jù)長(zhǎng)度
    const NSInteger totalSize = self.jjData.length;
    NSLog(@"當(dāng)前數(shù)據(jù)大姓て痢:%ld", totalSize);
}

#pragma mark NSURLSessionTaskDelegate

/**
 任務(wù)完成數(shù)據(jù)傳輸

 @param session 用戶創(chuàng)建的會(huì)話
 @param task 用戶創(chuàng)建的任務(wù)
 @param error 錯(cuò)誤信息
 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    if (nil == error) {
        NSLog(@"總數(shù)據(jù)大形娴小:%ld", self.jjData.length);
    }
}

假如需要實(shí)時(shí)顯示加載進(jìn)度,在
URLSession:dataTask:didReceiveResponse:responsecompletionHandler:方法中獲取響應(yīng)內(nèi)容的預(yù)期大小既琴,在URLSession:dataTask:didReceiveData:方法的中獲取當(dāng)前數(shù)據(jù)的大小占婉,最后在URLSession:task:didCompleteWithError:方法中關(guān)閉加載進(jìn)度。

除了resmue方法甫恩,URLSessionTask還提供了暫停和取消的方法逆济。

// 暫停任務(wù)
- (void)suspend;
// 取消任務(wù)
- (void)cancel;


總結(jié)

學(xué)習(xí)NSURLSession的目的是為了之后學(xué)習(xí)SDWebImage的Downloader模塊,Downloader是SDWebimage的核心模塊磺箕,包含了兩大類(lèi)SDWebImageDownloader和SDWebImageDownloaderOperation奖慌。在學(xué)習(xí)SDWebImageDownloaderOperation時(shí),會(huì)對(duì)NSURLSession的應(yīng)用做進(jìn)一步的闡述松靡。

AFNetworking庫(kù)也是基于NSURLSession封裝的简僧,等學(xué)習(xí)完SDWebImage的源碼,筆者會(huì)研究AFNetworking的源碼雕欺,希望今天的學(xué)習(xí)能起到一些幫助作用岛马。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末棉姐,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子啦逆,更是在濱河造成了極大的恐慌伞矩,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夏志,死亡現(xiàn)場(chǎng)離奇詭異乃坤,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)沟蔑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)湿诊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人瘦材,你說(shuō)我怎么就攤上這事厅须。” “怎么了宇色?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵九杂,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我宣蠕,道長(zhǎng)例隆,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任抢蚀,我火速辦了婚禮镀层,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘皿曲。我一直安慰自己唱逢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布屋休。 她就那樣靜靜地躺著坞古,像睡著了一般。 火紅的嫁衣襯著肌膚如雪劫樟。 梳的紋絲不亂的頭發(fā)上痪枫,一...
    開(kāi)封第一講書(shū)人閱讀 51,554評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音叠艳,去河邊找鬼奶陈。 笑死,一個(gè)胖子當(dāng)著我的面吹牛附较,可吹牛的內(nèi)容都是我干的吃粒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼拒课,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼徐勃!你這毒婦竟也來(lái)了事示?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤疏旨,失蹤者是張志新(化名)和其女友劉穎很魂,沒(méi)想到半個(gè)月后扎酷,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體檐涝,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年法挨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了谁榜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡凡纳,死狀恐怖窃植,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情荐糜,我是刑警寧澤巷怜,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站暴氏,受9級(jí)特大地震影響延塑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜答渔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一关带、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧沼撕,春花似錦宋雏、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至笼沥,卻和暖如春蚪燕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背敬拓。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工邻薯, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人乘凸。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓厕诡,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親营勤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子灵嫌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

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