AFNetWorking(3.0)源碼分析(二)——AFURLSessionManager

AFNetworking是基于NSURLSession實現(xiàn)的?;叵胍幌翹SURLSession的使用方式:

創(chuàng)建NSURLSessionConfig對象
用之前創(chuàng)建的NSURLSessionConfig對象創(chuàng)建配置NSURLSession對象。
用NSURLSession對象創(chuàng)建對應(yīng)的task對象 并用resume方法執(zhí)行之。
用delegate方法或completion block 響應(yīng)網(wǎng)絡(luò)事件及數(shù)據(jù)。
對應(yīng)于每次網(wǎng)絡(luò)會話(這里可以簡單理解為一個網(wǎng)頁),對應(yīng)一個NSURLSession對象,而每個會話,可以生成若干task對象用于數(shù)據(jù)的交互。

而在AFNet中, AFURLSessionManager作為核心類,封裝并提供了上述網(wǎng)絡(luò)交互功能。

AFURLSessionManager組成

AFNet運用了組合的設(shè)計模式,將不同功能搭建成AFURLSessionManager的功能。
AFURLSessionManager的主要屬性:

/**
The managed session.
*/
@property (readonly, nonatomic, strong) NSURLSession *session;

/**
The operation queue on which delegate callbacks are run.
*/
@property (readonly, nonatomic, strong) NSOperationQueue *operationQueue;

/**
Responses sent from the server in data tasks created with dataTaskWithRequest:success:failure: and run using the GET / POST / et al. convenience methods are automatically validated and serialized by the response serializer. By default, this property is set to an instance of AFJSONResponseSerializer.

@warning responseSerializer must not be nil.
*/
@property (nonatomic, strong) id <AFURLResponseSerialization> responseSerializer;

///-------------------------------
/// @name Managing Security Policy
///-------------------------------

/**
The security policy used by created session to evaluate server trust for secure connections. AFURLSessionManager uses the defaultPolicy unless otherwise specified.
*/
@property (nonatomic, strong) AFSecurityPolicy *securityPolicy;

if !TARGET_OS_WATCH

///--------------------------------------
/// @name Monitoring Network Reachability
///--------------------------------------

/**
The network reachability manager. AFURLSessionManager uses the sharedManager by default.
*/
@property (readwrite, nonatomic, strong) AFNetworkReachabilityManager *reachabilityManager;

endif

///----------------------------
/// @name Getting Session Tasks
///----------------------------

/**
The data, upload, and download tasks currently run by the managed session.
*/
@property (readonly, nonatomic, strong) NSArray <NSURLSessionTask *> *tasks;

/**
The data tasks currently run by the managed session.
*/
@property (readonly, nonatomic, strong) NSArray <NSURLSessionDataTask *> *dataTasks;

/**
The upload tasks currently run by the managed session.
*/
@property (readonly, nonatomic, strong) NSArray <NSURLSessionUploadTask *> *uploadTasks;

/**
The download tasks currently run by the managed session.
*/
@property (readonly, nonatomic, strong) NSArray <NSURLSessionDownloadTask *> *downloadTasks;

///-------------------------------
/// @name Managing Callback Queues
///-------------------------------

/**
The dispatch queue for completionBlock. If NULL (default), the main queue is used.
*/
@property (nonatomic, strong, nullable) dispatch_queue_t completionQueue;

/**
The dispatch group for completionBlock. If NULL (default), a private dispatch group is used.
*/
@property (nonatomic, strong, nullable) dispatch_group_t completionGroup;

AFNet的注釋很詳細,其屬性可以作如下分類

AFURLSessionManager所管理的Session對象
@property (readonly, nonatomic, strong) NSURLSession *session;

delegate所返回的NSOperationQueue
@property (readonly, nonatomic, strong) NSOperationQueue *operationQueue;

解析網(wǎng)絡(luò)返回數(shù)據(jù)的對象(遵循AFURLResponseSerialization協(xié)議)
@property (nonatomic, strong) id responseSerializer;

用于處理網(wǎng)絡(luò)連接安全處理策略的AFSecurityPolicy對象
@property (nonatomic, strong) AFSecurityPolicy *securityPolicy;

用于檢測網(wǎng)絡(luò)數(shù)據(jù)的AFNetworkReachabilityManager對象
@property (readwrite, nonatomic, strong) AFNetworkReachabilityManager *reachabilityManager;

當前的Session task
*tasks;

*dataTasks;

*uploadTasks;

*downloadTasks;

設(shè)置Call back隊列
在這里除了能設(shè)置Session的completion block外(默認為main block),還可以設(shè)置completion group。

看過這些分類,是不是覺得AFURLSessionManager也不是多么復雜了?確實,AFNet本就是一套簡潔的網(wǎng)絡(luò)框架,功能強大而結(jié)構(gòu)清晰。
下面,我們就一起看一看,利用AFURLSessionManager是如何完成一次簡單的網(wǎng)絡(luò)請求的。

運用AFURLSessionManager完成網(wǎng)絡(luò)請求

運用AFRULSessionManager獲取網(wǎng)絡(luò)數(shù)據(jù),僅需如下幾個步驟:

// step1. 初始化AFURLSessionManager對象
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];

// step2. 獲取AFURLSessionManager的task對象
NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
} else {
NSLog(@"Get Net data success!");
}
}];

// step3. 發(fā)動task
[dataTask resume];

OK,簡單的三步,就完成了對網(wǎng)絡(luò)數(shù)據(jù)的請求。

下面我們就一步步分析,這三步背后AFNet的源代碼是如何實現(xiàn)的。

初始化AFURLSessionManager

要進行網(wǎng)絡(luò)請求,第一步就是初始化AFURLSessionManager,調(diào)用函數(shù)

  • (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration
    1
    該函數(shù)很簡單,只有一個NSURLSessionConfiguration用來配置AFURLSessionManager所管理的NSURLSession對象。

它的實現(xiàn)代碼如下:

(instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
self = [super init];
if (!self) {
return nil;
}
// =============== 設(shè)置NSURLSession ===============
// 若configuration為nil,則采用默認defaultSessionConfiguration

if (!configuration) {
    configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
}

self.sessionConfiguration = configuration;
// session 的delegate callback queue, 最大并發(fā)為1 
self.operationQueue = [[NSOperationQueue alloc] init];
self.operationQueue.maxConcurrentOperationCount = 1;
// 初始化所管理的session
self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];

// =============== 設(shè)置response 數(shù)據(jù)序列化 ===============
self.responseSerializer = [AFJSONResponseSerializer serializer];

// =============== 設(shè)置網(wǎng)絡(luò)安全策略 ===============
self.securityPolicy = [AFSecurityPolicy defaultPolicy];

// =============== 設(shè)置網(wǎng)絡(luò)狀態(tài)監(jiān)控Manager(注意這里是一個全局單例實現(xiàn)) ===============

if !TARGET_OS_WATCH

self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];

endif

// =============== 設(shè)置存儲NSURL task與AFURLSessionManagerTaskDelegate的詞典(重點,在AFNet中,每一個task都會被匹配一個AFURLSessionManagerTaskDelegate 來做task的delegate事件處理) ===============
self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];

// =============== 設(shè)置AFURLSessionManagerTaskDelegate 詞典的鎖,確保詞典在多線程訪問時的線程安全===============
self.lock = [[NSLock alloc] init];
self.lock.name = AFURLSessionManagerLockName;

// =============== 為所管理的session的所有task設(shè)置完成塊(這里不是很明白,既然是初始化函數(shù),那么應(yīng)該沒有任何task在運行才是,怎么需要在這里設(shè)置完成塊呢???)===============
[self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
for (NSURLSessionDataTask *task in dataTasks) {
[self addDelegateForDataTask:task uploadProgress:nil downloadProgress:nil completionHandler:nil];
}

    for (NSURLSessionUploadTask *uploadTask in uploadTasks) {
        [self addDelegateForUploadTask:uploadTask progress:nil completionHandler:nil];
    }

    for (NSURLSessionDownloadTask *downloadTask in downloadTasks) {
        [self addDelegateForDownloadTask:downloadTask progress:nil destination:nil completionHandler:nil];
    }
}];

// =============== 返回初始化好的self ===============
return self;
}
這就是AFURLSessionManager的初始化函數(shù),主要是對其屬性進行初始化,要注意的是它的私有屬性

@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableTaskDelegatesKeyedByTaskIdentifier;

@property (readwrite, nonatomic, strong) NSLock *lock;

AFURLSessionManager會為每一個所管理的task對應(yīng)創(chuàng)建一個AFURLSessionManagerTaskDelegate對象,Manager會交ManagerTaskDelegate對象由來具體處理各個task事物,從而實現(xiàn)了同一個AFURLSessionManager對多個task的管理。

生成AFURLSessionManager的task對象

當初始化好AFURLSessionManager后,就需要獲取一個代表我們當前網(wǎng)絡(luò)請求的task了:

/**
Creates an NSURLSessionDataTask with the specified request.

@param request The HTTP request for the request.
@param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any.
*/

  • (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
    completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler;

當然還可以獲取download task 和upload task, 這里我們僅分析最簡單的data task。

其實現(xiàn)如下:

return [self dataTaskWithRequest:request uploadProgress:nil downloadProgress:nil completionHandler:completionHandler];
1
僅一行代碼,調(diào)用自身另一方法:

  • (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
    uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock
    downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock
    completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler {

    __block NSURLSessionDataTask *dataTask = nil;
    url_session_manager_create_task_safely(^{
    dataTask = [self.session dataTaskWithRequest:request];
    });

    [self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];

    return dataTask;
    }

上述方法完成了兩件事情:

  1. 生成一個data task對象,并返回。
  2. 為該data task對象生成一個匹配的AFURLSessionManagerTaskDelegate對象,并關(guān)聯(lián)之。

對于功能1,沒什么多說的,就是這里AFNet為了避免iOS 8.0以下版本中偶發(fā)的taskIdentifiers不唯一的bug,AFNet使用了

static void url_session_manager_create_task_safely(dispatch_block_t block) {
if (NSFoundationVersionNumber < NSFoundationVersionNumber_With_Fixed_5871104061079552_bug) {
// Fix of bug
// Open Radar:http://openradar.appspot.com/radar?id=5871104061079552 (status: Fixed in iOS8)
// Issue about:https://github.com/AFNetworking/AFNetworking/issues/2093
dispatch_sync(url_session_manager_creation_queue(), block);
} else {
block();
}
}

函數(shù)創(chuàng)建task對象。

其實現(xiàn)應(yīng)該是因為iOS 8.0以下版本中會并發(fā)地創(chuàng)建多個task對象,而同步有沒有做好,導致taskIdentifiers 不唯一…

對于功能二,AFNet為每一個task生成對應(yīng)的task delegate對象,我們則應(yīng)該重點了解一下。

  • (void)addDelegateForDataTask:(NSURLSessionDataTask *)dataTask
    uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock
    downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock
    completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
    {
    // 創(chuàng)建AFURLSessionManagerTaskDelegate對象
    AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init];
    // AFURLSessionManagerTaskDelegate與AFURLSessionManager建立相互關(guān)系
    delegate.manager = self;
    // 設(shè)置AF delegate的完成塊為用戶傳入的完成塊
    delegate.completionHandler = completionHandler;
    // 設(shè)置dataTask的taskDescription
    dataTask.taskDescription = self.taskDescriptionForSessionTasks;
    // ***** 將AF delegate對象與 dataTask建立關(guān)系
    [self setDelegate:delegate forTask:dataTask];
    // 設(shè)置AF delegate的上傳進度,下載進度塊。
    delegate.uploadProgressBlock = uploadProgressBlock;
    delegate.downloadProgressBlock = downloadProgressBlock;
    }

AFNet通過封裝AFURLSessionManagerTaskDelegate對象,對每個task 進行管理,而AFURLSessionManager僅需要管理建立task 與AF delegate的詞典即可,實現(xiàn)了AFURLSessionManager功能的下放。
那么我們這里重點看一下,AF delegate與task是如何建立關(guān)系的:

[self setDelegate:delegate forTask:dataTask];

實現(xiàn):

  • (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
    forTask:(NSURLSessionTask *)task
    {
    NSParameterAssert(task);
    NSParameterAssert(delegate);
    // 加鎖,確保詞典的線程安全
    [self.lock lock];
    // 將AF delegate放入以taskIdentifier標記的詞典中(同一個NSURLSession中的taskIdentifier是唯一的)
    self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
    // 為AF delegate 設(shè)置task 的progress監(jiān)聽
    [delegate setupProgressForTask:task];
    [self addNotificationObserverForTask:task];
    // 詞典操作完畢,解鎖
    [self.lock unlock];
    }

AFURLSessionManager會將每個AF delegate放入其詞典中,同時,AF delegate會監(jiān)聽每個task的進度,這是通過

[delegate setupProgressForTask:task];

實現(xiàn)的。我們繼續(xù)看 AF delegate 是如何監(jiān)聽task的各種進度的:

pragma mark - NSProgress Tracking

  • (void)setupProgressForTask:(NSURLSessionTask *)task {
    __weak typeof(task) weakTask = task;

    self.uploadProgress.totalUnitCount = task.countOfBytesExpectedToSend;
    self.downloadProgress.totalUnitCount = task.countOfBytesExpectedToReceive;
    [self.uploadProgress setCancellable:YES];
    [self.uploadProgress setCancellationHandler:^{
    typeof(weakTask) strongTask = weakTask;
    [strongTask cancel];
    }];
    [self.uploadProgress setPausable:YES];
    [self.uploadProgress setPausingHandler:^{
    typeof(weakTask) strongTask = weakTask;
    [strongTask suspend];
    }];
    if ([self.uploadProgress respondsToSelector:@selector(setResumingHandler:)]) {
    [self.uploadProgress setResumingHandler:^{
    typeof(weakTask) strongTask = weakTask;
    [strongTask resume];
    }];
    }

    [self.downloadProgress setCancellable:YES];
    [self.downloadProgress setCancellationHandler:^{
    typeof(weakTask) strongTask = weakTask;
    [strongTask cancel];
    }];
    [self.downloadProgress setPausable:YES];
    [self.downloadProgress setPausingHandler:^{
    typeof(weakTask) strongTask = weakTask;
    [strongTask suspend];
    }];

    if ([self.downloadProgress respondsToSelector:@selector(setResumingHandler:)]) {
    [self.downloadProgress setResumingHandler:^{
    typeof(weakTask) strongTask = weakTask;
    [strongTask resume];
    }];
    }

    // 這里為什么要用NSStringFromSelector 而不直接使用NSString???
    [task addObserver:self
    forKeyPath:NSStringFromSelector(@selector(countOfBytesReceived))
    options:NSKeyValueObservingOptionNew
    context:NULL];
    [task addObserver:self
    forKeyPath:NSStringFromSelector(@selector(countOfBytesExpectedToReceive))
    options:NSKeyValueObservingOptionNew
    context:NULL];

    [task addObserver:self
    forKeyPath:NSStringFromSelector(@selector(countOfBytesSent))
    options:NSKeyValueObservingOptionNew
    context:NULL];
    [task addObserver:self
    forKeyPath:NSStringFromSelector(@selector(countOfBytesExpectedToSend))
    options:NSKeyValueObservingOptionNew
    context:NULL];

    [self.downloadProgress addObserver:self
    forKeyPath:NSStringFromSelector(@selector(fractionCompleted))
    options:NSKeyValueObservingOptionNew
    context:NULL];
    [self.uploadProgress addObserver:self
    forKeyPath:NSStringFromSelector(@selector(fractionCompleted))
    options:NSKeyValueObservingOptionNew
    context:NULL];
    }

上面的代碼可以分為兩個部分,

  1. 設(shè)置AF delegate的uploadProgress 和 downloadProgress。(注意為了防止對block對象截取產(chǎn)生的循環(huán)引用,將傳入的task設(shè)置為了weak。但是這里的循環(huán)引用在哪里呢??? 其實這里鑒于block所造成的一系列循環(huán)引用的問題,AFNet采取了一種防御式編程的方法,對于沒有必要在block中進行強引用的變量,一律采用弱引用。并且,當task置為nil后,block也沒有理由繼續(xù)strong引用task變量)
  2. 利用KVO, 監(jiān)聽task屬性及uploadProgress,downloadProgress屬性的變化,進一步監(jiān)聽task的數(shù)據(jù)傳輸進程。

看到了KVO,那我們就直接看其對應(yīng)的響應(yīng)函數(shù):

  • (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
    if ([object isKindOfClass:[NSURLSessionTask class]]) {
    if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesReceived))]) {
    self.downloadProgress.completedUnitCount = [change[@"new"] longLongValue];
    } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesExpectedToReceive))]) {
    self.downloadProgress.totalUnitCount = [change[@"new"] longLongValue];
    } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesSent))]) {
    self.uploadProgress.completedUnitCount = [change[@"new"] longLongValue];
    } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesExpectedToSend))]) {
    self.uploadProgress.totalUnitCount = [change[@"new"] longLongValue];
    }
    }
    else if ([object isEqual:self.downloadProgress]) {
    if (self.downloadProgressBlock) {
    self.downloadProgressBlock(object);
    }
    }
    else if ([object isEqual:self.uploadProgress]) {
    if (self.uploadProgressBlock) {
    self.uploadProgressBlock(object);
    }
    }
    }

很簡單,當監(jiān)控的Task屬性改變時,同時改變由AF delegate所管理持有的Progress對象的屬性。
同時,當AF delegate的Progress對象屬性改變時,調(diào)用對應(yīng)的progress block。

NSURLSessionDelegate 的響應(yīng)

因為AFURLSessionManager所管理的NSURLSession對象的delegate被設(shè)置為AFURLSessionManager自身,因此所有的NSURLSessionDelegate回調(diào)方法的目的地都是AFURLSessionManager,而AFURLSessionManager又會根據(jù)是否需要具體處理,會將屬于AF delegate要響應(yīng)的delegate,傳遞到對應(yīng)的AF delegate去。
AFURLSessionManager 和 AFURLSessionManagerTaskDelegate 相應(yīng)的delegate回調(diào)方法如下:

AFURLSessionManager 需要處理的NSURLSessionDelegate:
這里寫圖片描述

AFURLSessionManagerTaskDelegate 需要處理的NSURLSessionDelegate:
這里寫圖片描述

當AFURLSessionManager 覺得應(yīng)該有AF delegate來處理該事件時,會取出對應(yīng)task的delegate,并將該事件原封不動的傳遞到delegate。
其實細看AF delegate所實現(xiàn)的NSURLSessionDelegate也不多,僅三條:

-URLSession:task:didCompleteWithError:
-URLSession:dataTask:didReceiveData:
-URLSession:downloadTask:didFinishDownloadingToURL:

可以看出,屬于AF task delegate處理的回調(diào),兩條是對于completion的處理,另一條則是對于每個task,分別接受并記錄其receive data。

而AFURLSessionManager對于NSSession的回調(diào)處理相對簡單,不外乎兩步:

  1. 如果有對應(yīng)的user block,則將當前NSSession block傳遞至user block(此處可能會利用user block的返回值,來繼續(xù)下一步操作)。
  2. 如果需要AF task delegate處理,則將該回調(diào)事件傳給相應(yīng)的AF task delegate。

我們可以看下面幾個例子:

  • (void)URLSession:(NSURLSession *)session
    task:(NSURLSessionTask *)task
    willPerformHTTPRedirection:(NSHTTPURLResponse *)response
    newRequest:(NSURLRequest *)request
    completionHandler:(void (^)(NSURLRequest *))completionHandler
    {
    NSURLRequest *redirectRequest = request;
    // step1. 看是否有對應(yīng)的user block
    if (self.taskWillPerformHTTPRedirection) {
    redirectRequest = self.taskWillPerformHTTPRedirection(session, task, response, request);
    }

    if (completionHandler) {
    // step2. 運用user block返回值或是原始值,使NSSession事件繼續(xù)
    completionHandler(redirectRequest);
    }
    }

  • (void)URLSession:(NSURLSession *)session
    task:(NSURLSessionTask *)task
    didCompleteWithError:(NSError *)error
    {
    // step1. 應(yīng)交由AF task delegate處理的事件,取出對應(yīng)AF task delegate,
    AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];

    // delegate may be nil when completing a task in the background
    if (delegate) {
    // step2. 將事件交由AF task delegate處理
    [delegate URLSession:session task:task didCompleteWithError:error];
    // NOTE: 此處是session task最終的回調(diào)函數(shù),task不會再返回任何信息。因此刪除對應(yīng)的AF task delegate
    [self removeDelegateForTask:task];
    }
    // step3. 若有對應(yīng)的user block,則調(diào)用之
    if (self.taskDidComplete) {
    self.taskDidComplete(session, task, error);
    }
    }

AFURLSessionManager 與 AFURLSessionManagerTaskDelegate 的分工

到這里我們可以想一想,既然NSURLSession的delegate是AFURLSessionManager對象,那么為什么不在AFURLSessionManager中處理所有的事件回調(diào),搞出來一個AFURLSessionManagerTaskDelegate干什么?

我們知道,NSURLSession的回調(diào)有很多,而當我們啟動一個task,真正想要獲取的信息是什么呢?就是網(wǎng)絡(luò)請求最終所返回的數(shù)據(jù)(我所進行的網(wǎng)絡(luò)操作成功或是失敗,服務(wù)器為我返回的數(shù)據(jù))唄! 其它的回調(diào),什么認證質(zhì)詢,task需要新的body stream,什么request即將重定向, 統(tǒng)統(tǒng)都是浮云,都是為了我們能夠最終獲取到服務(wù)器返回的數(shù)據(jù)所服務(wù)的。

另外我們也想要知道我們的網(wǎng)絡(luò)請求的進度。
總結(jié)為兩點:

  1. 獲取最終返回數(shù)據(jù)
  2. 獲知當前請求的進度

于是,AFNetWorking 便在紛繁復雜的回調(diào)處理中,特意抽象出AFURLSessionManagerTaskDelegate,用于應(yīng)付網(wǎng)絡(luò)返回數(shù)據(jù)的處理(包括保存中間值,序列化返回值,錯誤處理)和網(wǎng)絡(luò)請求進度。
這樣做可以使代碼結(jié)構(gòu)更分明,邏輯更清晰。
這在AFURLSessionManagerTaskDelegate的聲明中也可以看出一二, 其屬性按功能分類就兩種,一種用來保存服務(wù)器返回數(shù)據(jù)及completion回調(diào),另一種就是反應(yīng)當前網(wǎng)絡(luò)處理進度:

@interface AFURLSessionManagerTaskDelegate : NSObject <NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate>
@property (nonatomic, weak) AFURLSessionManager *manager;
@property (nonatomic, strong) NSMutableData *mutableData; // 保存服務(wù)器返回的數(shù)據(jù)
@property (nonatomic, strong) NSProgress *uploadProgress; // 上傳進度
@property (nonatomic, strong) NSProgress *downloadProgress; // 下載進度
@property (nonatomic, copy) NSURL *downloadFileURL; // 下載文件目的存儲地址
@property (nonatomic, copy) AFURLSessionDownloadTaskDidFinishDownloadingBlock downloadTaskDidFinishDownloading;
@property (nonatomic, copy) AFURLSessionTaskProgressBlock uploadProgressBlock;
@property (nonatomic, copy) AFURLSessionTaskProgressBlock downloadProgressBlock;
@property (nonatomic, copy) AFURLSessionTaskCompletionHandler completionHandler;
@end

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

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

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