SDWebImage學習筆記之NSURLSession

NSURLSession概述

NSURLSession是從iOS7開始使用,用于替代NSURLConnection進行網(wǎng)絡數(shù)據(jù)傳輸?shù)念悺V腁FNetworking庫的2.0版本采用的NSURLConnection,但是從3.0版本開始,已經(jīng)用NSURLSession替換了NSURLConnection。

NSURLSession可以與delegate(代理)綁定,在一個會話的生命周期內(nèi),delegate會被某些事件調用,例如服務端認證或者確定加載的資源是否應該轉化為下載。

NSURLSession實例是線程安全的,它會創(chuàng)建NSURLSessionTask對象來執(zhí)行數(shù)據(jù)的加載。被創(chuàng)建的NSURLSessionTask對象初始化狀態(tài)是suspend(掛起),需要調用resume(恢復)方法來執(zhí)行。


NSURLSessionTask

NSURLSessionTask有四個子類:NSURLSessionDataTask、NSURLSessionUploadTask和NSURLSessionDownloadTask,NSURLSessionStreamTask。

  1. NSURLSessionDataTask用于執(zhí)行普通的任務,例如請求或上傳數(shù)據(jù)。
  2. NSURLSessionUploadTask繼承自NSURLSessionUploadTask用于上傳文件或數(shù)據(jù)到服務器。
  3. NSURLSessionDownloadTask會直接將響應數(shù)據(jù)寫入臨時文件,默認下載到沙盒的temp目錄下。下載完成后,delegate會接收到URLSession:downloadTask:didFinishDownloadingToURL: 消息。
  4. NSURLSessionStreamTask用于建立一個 TCP/IP 連接,自iOS9以后開始使用。

NSURLSessionConfiguration

NSURLSessionConfiguration是NSURLSession的配置類,用于生成NSURLSession對象。
NSURLSessionConfiguration有三種初始化方式:

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

NSURLSession使用

NSURLSession提供了兩種方法來創(chuàng)建會話:

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

第二個方法可以傳入delegate來監(jiān)聽會話事件,delegate需要遵循NSURLSessionDelegate協(xié)議且會被強引用,還可以傳入NSOperationQueue對象來指定delegate在哪個隊列被調用,傳入值為nil時,session會默認創(chuàng)建一個串行隊列來執(zhí)行delegate的方法。

創(chuàng)建完會話之后,需要創(chuàng)建一個任務來執(zhí)行具體的網(wǎng)絡傳輸操作。

// 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;
普通任務獲取資訊列表:
// 配置URL
NSURL *url = [NSURL URLWithString:@"http://toutiao-ali.juheapi.com/toutiao/index"];
// 配置URLRequest
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setValue:@"APPCODE fd4e0a674e274e46ad3e26ab508ff21c" forHTTPHeaderField:@"Authorization"];
// 配置全局會話
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
// 返回掛起的普通任務
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);
}];
// 恢復普通任務
[dataTask resume];

執(zhí)行resume方法后任務才會開始加載數(shù)據(jù),并在回調中返回響應,不然task永遠是掛起狀態(tài)。

下載任務下載圖片資源:
// 配置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"];
// 配置全局會話
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];
// 返回掛起的下載任務
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    // 返回沙盒tmp目錄的臨時文件
    NSLog(@"%@", location);
}];
// 恢復下載任務
[downloadTask resume];
通過代理方法實現(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"];
// 配置全局會話
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
// 傳入代理對象
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];
// 返回掛起的普通任務,不用completionHandler返回數(shù)據(jù)
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url];
// 恢復下載任務
[dataTask resume];

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

#pragma mark NSURLSessionDataDelegate

/**
 任務收到服務器的初始響應

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

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

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

#pragma mark NSURLSessionTaskDelegate

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

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

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

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

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


總結

學習NSURLSession的目的是為了之后學習SDWebImage的Downloader模塊,Downloader是SDWebimage的核心模塊,包含了兩大類SDWebImageDownloader和SDWebImageDownloaderOperation。在學習SDWebImageDownloaderOperation時,會對NSURLSession的應用做進一步的闡述。

AFNetworking庫也是基于NSURLSession封裝的,等學習完SDWebImage的源碼,筆者會研究AFNetworking的源碼,希望今天的學習能起到一些幫助作用。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容