AFNetWorking源碼之NSURLSession系列概述

1 基本說明

記得我剛作iOS的時候,那時候仍是ASI和AFN共存,甚至ASI使用比例還多點,一轉眼幾年過去,ASI基本已經消失了,AFN基本成了iOS項目的標配。我雖然之前也有看過AFN2.x的源碼,可是對於AFN3.x的源碼一直沒有本身閱讀。接下來我會對AFN3.x學習而且寫博客記錄。得益於NSURLSession的強大功能,ANF3.0放棄了NSURLConnection這一部分,讓代碼簡化了不少,可是功能卻更加豐富。我以爲在學習AFN以前,有必要仔細瞭解NSURLSessionhttps相關,否則會有不少地方疑惑不解,具體能夠看個人git倉庫![iOSSourceCodeStudy
](https://github.com/huang30351...。同時我強烈推薦瀏覽一下NSURLSession.h這個文件。git

2 相互關係

咱們首先來看一下一個簡單的NSURLSession請求代碼:github

NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
    
    NSURLRequest *request = [[NSURLRequest alloc]initWithURL:[NSURL URLWithString:bigPic]];
    
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];
    [dataTask resume];

從上面咱們發現,咱們要發送一個網絡請求,須要新建一個NSURLSession,新建一個NSURLSession又須要一個NSURLSessionConfiguration,而且還須要一些代理方法。同時咱們須要一個NSURLSessionDataTask。因此說,咱們的NSRULSession
網絡請求系統包括一個session、一個configuration、一個Task已經Task附帶的delegate。api

  • 一個NSURLSession,總共只有一個類,也是最核心的類,他有一個對應的代理NSURLSessionDelegate緩存

  • 一個NSURLSessionConfiguration,總共有三種模式。服務器

  • 一個NSURLSessionTaskNSURLSessionTask是抽閒類,對應的代理NSURLSessionTaskDelegate。咱們具體使用的時候,會使用他的三種子類,並且每一個子類都有對應的delegate。網絡

3 一個NSURLSession

首先咱們看一下NSRULSession.h裏面關於NSURLSession的部分。咱們把它分爲初始化部分、屬性部分、dataTask部分、uploadTask部分、downloadTask部分。也就是說其餘不少類都是圍繞着下面這幾個api衍生的。後面咱們會每一個部分分析。session

//初始化部分
@property (class, readonly, strong) NSURLSession *sharedSession;
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(nullable id <NSURLSessionDelegate>)delegate delegateQueue:(nullable NSOperationQueue *)queue;

//屬性部分
@property (readonly, retain) NSOperationQueue *delegateQueue;
@property (nullable, readonly, retain) id <NSURLSessionDelegate> delegate;
@property (readonly, copy) NSURLSessionConfiguration *configuration;

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

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

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

3.1 Block的NSURLSession的api

咱們都知道,NSRULConnection除了一套使用代理的API,還有一套對應的使用Block的api。NSURLSession也不列外。使用這一套api就不用實現代理方法。和delegate同樣,Block也有dataTask系列、downloadTask系列、uploadTask系列。具體看下面:app

//dataTask系列
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler{
    
}
- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler{
    
}
//unloadTast系列
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler{
    
}
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(nullable NSData *)bodyData completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler{
    
}
//downloadTask系列
- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler{
    
}
- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler{
    
}
- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData completionHandler:(void (^)(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler{
    
}

3.2 Block的NSURLSession使用

用dataTask下載一張圖片,而後用imageView顯示。ide

-(IBAction)requestBlockTaskTest:(id)sender{
    [self clear];
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLRequest *request = [[NSURLRequest alloc]initWithURL:[NSURL URLWithString:bigPic]];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        UIImage *image = [[UIImage alloc]initWithData:data];
        self.imageView.image = image;
    }];
    [dataTask resume];
}

4 一個NSURLSessionConfiguration

首先看一下NSURLSessionConfiguration部分。從這個名字,咱們能夠預感到這個是與session的配置相關的,的確也是這樣。總共有三種類型的configuratin,另外還有不少屬性,好比配置緩存策略的requestCachePolicy,請求超時的timeoutIntervalForRequest,添加額外請求頭的HTTPAdditionalHeaders,其餘還有不少屬性這裏就不一一說了,具體看源碼:學習

//默認的配置會將緩存存儲在磁盤上
@property (class, readonly, strong) NSURLSessionConfiguration *defaultSessionConfiguration;
//第二種瞬時會話模式不會建立持久性存儲的緩存.
@property (class, readonly, strong) NSURLSessionConfiguration *ephemeralSessionConfiguration;
//第三種後臺會話模式容許程序在後臺進行上傳下載工做
+ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier;
//各類屬性
@property NSURLRequestCachePolicy requestCachePolicy;
@property NSTimeInterval timeoutIntervalForRequest;
@property (nullable, copy) NSDictionary *HTTPAdditionalHeaders;

5 一個NSURLSessionTask

從上面NSURLSession初始化一個請求的時候,咱們發現NSURLSessionTask並不能直接使用,只能使用他的子類。具體以下:

  • NSURLSessionTask抽象類。有對應的代理NSURLSessionTaskDelegate,並且這個代理繼承了NSURLSessionDelegate代理。

  • NSURLSessionDataTaskNSURLSessionTask的子類。有對應的代理NSURLSessionTaskDelegate,並且這個代理繼承了NSURLSessionTaskDelegate代理。咱們通常網絡請求,就用這個類。

  • NSURLSessionDownloadTaskNSURLSessionTask的子類。有對應的代理NSURLSessionDownloadDelegate,並且這個代理繼承了NSURLSessionTaskDelegate代理。這個主要用於下載大文件等。

  • NSURLSessionUploadTaskNSURLSessionDataTask的子類。有對應的代理及時父類代理NSURLSessionDownloadDelegate。這個主要用於處理上傳請求如上傳圖片。

從上面咱們發現Task和delegate有一套對應的繼承關係:

  • NSURLSessionTask (抽象類,NSURLSessionTaskDelegate)

    • NSURLSessionDataTask (NSURLSessionDataDelegate)

      • NSURLSessionUploadTask (NSURLSessionDataDelegate)

    • NSURLSessionDownloadTask (NSURLSessionDownloadDelegate)

  • NSURLSessionDelegate

    • NSURLSessionTaskDelegate

      • NSURLSessionDataDelegate

      • NSURLSessionDownloadDelegate

從繼承關係上,咱們就能夠理解在初始化的時候,只經過設置NSURLSession對象的delegate就能夠了。由於根據不一樣的task,其實就是設置了不一樣的delegate。這個設計避免了屢次設置delegate的狀況,同時也根據不一樣的task實現不一樣的delegate方法。真是一個很絕妙的設計。

6 代理說明

6.1 NSURLSessionDelegate

接下來咱們看看NSURLSession的delegate對象NSURLSessionDelegate的方法,當一個session遇到錯誤、或者須要認證、應用進入後臺都會調用下面的代理方法:

//當一個session遇到系統錯誤或者未檢測到的錯誤的時候,就會調用這個方法。
- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable NSError *)error{

}
//當請求須要認證、或者https證書認證的時候,咱們就須要在這個方法裏面處理。
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler{
    
}
//若是應用進入後臺、這個方法會被調用。咱們在這裏能夠對session發起的請求作各類操做好比請求完成的回調等。
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {

}

6.2 NSURLSessionTaskDelegate

/*
 當請求重定向的時候調用這個方法。咱們必須設置一個新的`NSURLRequest`對象傳入completionHandler來重定向新的請求,可是當`session`是background模式的時候,這個方法不會被調用。
 */
- (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{

}
/*
 當task的統計信息收集好了之後,調用這個方法。
 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics {

}
/*
 當一個task出錯的時候,會調用這個方法。若是error是nil,也會調用這個方法,表示task完成。
 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didCompleteWithError:(nullable NSError *)error{
    NSLog(@"數據返回之後,無論有錯沒錯都回調用,若是沒錯,error及時nil");
}

6.3 NSURLSessionDataDelegate

/*
 當一個task接收到返回信息。當全部信息都接收完畢之後,completionHandler會被調用。咱們能夠在這裏取消一個網絡請求或者把一個datatask轉換爲downloadtask。若是沒有實現這個代理方法,咱們也能夠經過task的response屬性獲取到對應的數據。background模式的uploadtask不會調用這個方法。
 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler{

}
/*
 當一個datatask轉換爲一個downloadtask之後會調用。
 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask{
    // 容許處理服務器的響應,纔會繼續接收服務器返回的數據
    completionHandler(NSURLSessionResponseAllow);
}
/*
 暫時忽略,這個是和數據流相關的。無論了
 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didBecomeStreamTask:(NSURLSessionStreamTask *)streamTask{

}
/*
 當data可使用的時候,調用這個方法。咱們能夠在這裏獲取data。
 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
    didReceiveData:(NSData *)data{

}
/*
 容許咱們在這裏調用completionHandler緩存data,或者傳入nil來禁止緩存
 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
 willCacheResponse:(NSCachedURLResponse *)proposedResponse
 completionHandler:(void (^)(NSCachedURLResponse * _Nullable cachedResponse))completionHandler{

}

6.4 NSURLSessionDownloadDelegate

/*
    當一個下載task任務完成之後,這個方法會被調用。咱們能夠在這裏移動或者複製download的數據
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location{

}
/*
 獲取下載進度
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
      didWriteData:(int64_t)bytesWritten
 totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{

}
/*
 重啓一個下載任務(好比下載一半後中止而後過一點時間繼續)。若是下載出錯,`NSURLSessionDownloadTaskResumeData`裏面包含從新開始下載的數據。
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
 didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes{

}

7 NSURLSession的綜合使用案列

分別用三種不一樣方式下載一張圖片而後在imageView上顯示。

#import "ViewController.h"

static NSString *const bigPic = @"http://i1.piimg.com/4851/d1498fea89ae3bc1.png";
static NSString *const smallPic = @"http://i1.piimg.com/4851/97aef4680d359905.png";

@interface ViewController ()<NSURLSessionDelegate>
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property(nonatomic,strong)NSMutableData *data;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // Do any additional setup after loading the view, typically from a nib.
}

- (IBAction)requestDataTest:(id)sender {
     [self clear];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
    NSURLRequest *request = [[NSURLRequest alloc]initWithURL:[NSURL URLWithString:bigPic]];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];
    [dataTask resume];
}


- (IBAction)requestDownloadTest:(id)sender {
     [self clear];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
    NSURLRequest *request = [[NSURLRequest alloc]initWithURL:[NSURL URLWithString:bigPic]];
    NSURLSessionDownloadTask *dataTask = [session downloadTaskWithRequest:request];
    [dataTask resume];
}

-(IBAction)requestBlockTaskTest:(id)sender{
    [self clear];
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLRequest *request = [[NSURLRequest alloc]initWithURL:[NSURL URLWithString:bigPic]];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        UIImage *image = [[UIImage alloc]initWithData:data];
        self.imageView.image = image;
    }];
    [dataTask resume];
}

-(void)clear{
    self.imageView.image = nil;
}

//==============================NSURLSessionDelegate========================
#pragma NSURLSessionDelegate
//當一個session遇到系統錯誤或者未檢測到的錯誤的時候,就會調用這個方法。
- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable NSError *)error{

}
//當請求須要認證、或者https證書認證的時候,咱們就須要在這個方法裏面處理。
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler{
    
}
//若是應用進入後臺、這個方法會被調用。咱們在這裏能夠對session發起的請求作各類操做好比請求完成的回調等。
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {

}

//==================================NSURLSessionTaskDelegate====================
#pragma NSURLSessionTaskDelegate
/*
 當請求重定向的時候調用這個方法。咱們必須設置一個新的`NSURLRequest`對象傳入completionHandler來重定向新的請求,可是當`session`是background模式的時候,這個方法不會被調用。
 */
- (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{
    NSLog(@"");
}
/*
 當task的統計信息收集好了之後,調用這個方法。
 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics {

}
/*
 當一個task出錯的時候,會調用這個方法。若是error是nil,也會調用這個方法,表示task完成。
 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didCompleteWithError:(nullable NSError *)error{
    NSLog(@"數據返回之後,無論有錯沒錯都回調用,若是沒錯,error及時nil");
    if (self.data) {
        self.imageView.image = [UIImage imageWithData:self.data];
        self.data = nil;
    }
}

//==================================NSURLSessionDataDelegate=====================================
#pragma NSURLSessionDataDelegate
/*
 當一個task接收到返回信息。當全部信息都接收完畢之後,completionHandler會被調用。咱們能夠在這裏取消一個網絡請求或者把一個datatask轉換爲downloadtask。若是沒有實現這個代理方法,咱們也能夠經過task的response屬性獲取到對應的數據。background模式的uploadtask不會調用這個方法。
 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler{
    self.data = nil;
    self.data = [NSMutableData data];
    // 容許處理服務器的響應,纔會繼續接收服務器返回的數據
    completionHandler(NSURLSessionResponseAllow);
}
/*
 當一個datatask轉換爲一個downloadtask之後會調用。
 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask{
    
}
/*
 暫時忽略,這個是和數據流相關的。無論了
 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didBecomeStreamTask:(NSURLSessionStreamTask *)streamTask{

}
/*
 當data可使用的時候,調用這個方法。咱們能夠在這裏獲取data。
 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
    didReceiveData:(NSData *)data{
    [self.data appendData:data];
    NSLog(@"具體數據在URLSession:(NSURLSession *)session task:(NSURLSessionTask *)taskdidCompleteWithError:(nullable NSError *)error處理");
}
/*
 容許咱們在這裏調用completionHandler緩存data,或者傳入nil來禁止緩存
 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
 willCacheResponse:(NSCachedURLResponse *)proposedResponse
 completionHandler:(void (^)(NSCachedURLResponse * _Nullable cachedResponse))completionHandler{

}
//==================================NSURLSessionDownloadTask=================================
#pragma NSURLSessionDownloadTask
/*
    當一個下載task任務完成之後,這個方法會被調用。咱們能夠在這裏移動或者複製download的數據
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location{
    NSString *path = location.absoluteString;
    UIImage *image = [[UIImage alloc]initWithData:[NSData dataWithContentsOfURL:location]];
    self.imageView.image = image;
    NSLog(@"數據下載完成之後,會保存在一個location的地方。%@",location);
}
/*
 獲取下載進度
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
      didWriteData:(int64_t)bytesWritten
 totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
    NSLog(@"總得數據大小%lld----",bytesWritten);
}
/*
 重啓一個下載任務(好比下載一半後中止而後過一點時間繼續)。若是下載出錯,`NSURLSessionDownloadTaskResumeData`裏面包含從新開始下載的數據。
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
 didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes{

}
@end
相關文章
相關標籤/搜索