前言:URLSesstion實現網絡請求的步驟
// 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. 發動task [dataTask resume];
下面可以看下AF如何實現這三個步驟的:
step1:實現生成Sesstion
核心屬性
/** 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;
核心方法解析
initWithSesstionConfiguration
(instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration { self = [super init]; if (!self) { return nil; } // =============== 設置NSURLSession =============== // 若configuration為nil,則采用默認defaultSessionConfiguration if (!configuration) { configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; } self.sessionConfiguration = configuration; // session 的delegate callback queue, 最大並發為1 self.operationQueue = [[NSOperationQueue alloc] init]; self.operationQueue.maxConcurrentOperationCount = 1; // 初始化所管理的session self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue]; // =============== 設置response 數據序列化 =============== self.responseSerializer = [AFJSONResponseSerializer serializer]; // =============== 設置網絡安全策略 =============== self.securityPolicy = [AFSecurityPolicy defaultPolicy]; // =============== 設置網絡狀態監控Manager(注意這里是一個全局單例實現) =============== #if !TARGET_OS_WATCH self.reachabilityManager = [AFNetworkReachabilityManager sharedManager]; #endif // =============== 設置存儲NSURL task與AFURLSessionManagerTaskDelegate的詞典(重點,在AFNet中,每一個task都會被匹配一個AFURLSessionManagerTaskDelegate 來做task的delegate事件處理) =============== self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init]; // =============== 設置AFURLSessionManagerTaskDelegate 詞典的鎖,確保詞典在多線程訪問時的線程安全=============== self.lock = [[NSLock alloc] init]; self.lock.name = AFURLSessionManagerLockName; // =============== 為所管理的session的所有task設置完成塊(這里不是很明白,既然是初始化函數,那么應該沒有任何task在運行才是,怎么需要在這里設置完成塊呢???)=============== [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; }
總結:1.初始化sesstion,opretion,安全策略,網絡可達性,序列化/反序列化,data數組,downLoadData數組,upLoadData數組
2.進入了sesstion的sesstionWithConfiguration的方法里面,傳入delegate
Setp2:生成Task
- (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.dataTaskWithRequest建立task
2.addDelegatForDataTask建立每一個delegate管理每個task
- (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 {
// 創建AFURLSessionManagerTaskDelegate對象 AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init]; // 設置AF delegate的完成塊為用戶傳入的完成塊 delegate.completionHandler = completionHandler; // 設置dataTask的taskDescription dataTask.taskDescription = self.taskDescriptionForSessionTasks; // 設置AF delegate的上傳進度,下載進度塊。 delegate.uploadProgressBlock = uploadProgressBlock; delegate.downloadProgressBlock = downloadProgressBlock; // AFURLSessionManagerTaskDelegate與AFURLSessionManager建立相互關系 delegate.manager = self; // ***** 將AF delegate對象與 dataTask建立關系 [self setDelegate:delegate forTask:dataTask]; }
- (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 設置task 的progress監聽 [delegate setupProgressForTask:task]; [self addNotificationObserverForTask:task]; // 詞典操作完畢,解鎖 [self.lock unlock]; }
總結:1.初始化dataDlegate 2.建立block對應delegate的關系 3.建立task和delegate的對應關系
Setp3.delegate之間的傳遞
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { // step1. 應交由AF task delegate處理的事件,取出對應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最終的回調函數,task不會再返回任何信息。因此刪除對應的AF task delegate [self removeDelegateForTask:task]; } // step3. 若有對應的user block,則調用之 if (self.taskDidComplete) { self.taskDidComplete(session, task, error); } }
1.獲取對應task的delegate,delegateForTask
2.調用AF的delegate的對應的complete方法,傳給了AFD
3.判斷,如果有block,設置block回調
AFNetworkingSesstionDelegate
@interface AFURLSessionManagerTaskDelegate : NSObject <NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate> @property (nonatomic, weak) AFURLSessionManager *manager; @property (nonatomic, strong) NSMutableData *mutableData; // 保存服務器返回的數據 @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
編者寄語,AFM對sesstionManager的封裝,首先是基於實現幾個步驟:1.初始化sesstionManager 2.初始化Task 3.回調的傳遞。
AFM在InitConfigution里面初始化了sesstion和相關的其它屬性,完成了第一個問題。
AFM在dataTask方法里面初始化了 sesstion的dataTask,並且為每個dataTask分配了一個delegate
AFM在setdelegate里面將sesstion的回調傳遞給AF,如果有回調,使用delegatForTask方法,獲取AF的delegate,如果有Block,賦值給Block
為什么不在Managter方法里面直接設置delelgate獲取Bblock呢,而使用了中間層的AFD