AFNetworking 3.0 使用詳解 和 源碼解析實現原理
AFN原理&& AFN如何使用RunLoop來實現的:
NSString * requestURL = @"http://119.254.98.136/api/v1/web/homepage"; // AFHTTPSessionManager * manager =[[AFHTTPSessionManager alloc] init]; AFHTTPSessionManager * manager =[AFHTTPSessionManager manager]; [manager GET:requestURL parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSLog(@"請求成功了!"); NSLog(@"%@",responseObject); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"請求失敗了!"); }];
1、
- (NSURLSessionDataTask *)GET:(NSString *)URLString parameters:(id)parameters progress:(void (^)(NSProgress * _Nonnull))downloadProgress success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure { NSURLSessionDataTask*dataTask = [self dataTaskWithHTTPMethod:@"GET" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:downloadProgress success:success failure:failure]; [dataTask resume]; return dataTask; }
2、如果序列化失敗,就直接執行了failure block,否則繼續3
- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method URLString:(NSString *)URLString parameters:(id)parameters uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress success:(void (^)(NSURLSessionDataTask *, id))success failure:(void (^)(NSURLSessionDataTask *, NSError *))failure { NSError *serializationError = nil; NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError]; if (serializationError) { if (failure) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wgnu" dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ failure(nil, serializationError); }); #pragma clang diagnostic pop } return nil; } __block NSURLSessionDataTask *dataTask = nil; dataTask = [self dataTaskWithRequest:request uploadProgress:uploadProgress downloadProgress:downloadProgress completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) { if (error) { if (failure) { failure(dataTask, error); } } else { if (success) { success(dataTask, responseObject); } } }]; return dataTask; }
3、
- (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; }
4、對dataTask設置請求之後的回調Delegate和處理block
- (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 *delegate = [[AFURLSessionManagerTaskDelegate alloc] init]; delegate.manager = self; delegate.completionHandler = completionHandler; dataTask.taskDescription = self.taskDescriptionForSessionTasks; [self setDelegate:delegate forTask:dataTask]; delegate.uploadProgressBlock = uploadProgressBlock; delegate.downloadProgressBlock = downloadProgressBlock; }
#pragma clang diagnostic push #pragma clang diagnostic ignored "-Wgnu" dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ failure(nil, serializationError); }); #pragma clang diagnostic pop
表示在這個區間裏忽略一些特定的clang的編譯警告,因為AFNetworking作為一個庫被其他項目引用,所以不能全局忽略clang的一些警告,只能在有需要的時候局部這樣做,作者喜歡用?:符號,所以經常見忽略-Wgnu警告的寫法
NSURLConnection
是 Foundation URL 加載系統的基石。一個 NSURLConnection
異步地加載一個 NSURLRequest
對象,調用 delegate 的 NSURLResponse
/ NSHTTPURLResponse
方法,其 NSData
被發送到服務器或從服務器讀取;delegate 還可用來處理 NSURLAuthenticationChallenge
、重定向響應、或是決定 NSCachedURLResponse
如何存儲在共享的 NSURLCache
上。
NSOperation
是抽象類,模擬單個計算單元,有狀態、優先級、依賴等功能,可以取消。
AFURLConnectionOperation將兩者結合,
作為 NSOperation
的子類,遵循 NSURLConnectionDelegate
的方法,可以從頭到尾監視請求的狀態,並儲存請求、響應、響應數據等中間狀態。
創建 AFURLConnectionOperation
並把它安排進 NSOperationQueue
,通過設置 NSOperation
的新屬性 completionBlock
,指定操作完成時如何處理 response 和 response data(或是請求過程中遇到的錯誤)。
AFNetworking 3.0 實現完全基於NSURLSessionTask進行封裝,NSURLSessionTask 是蘋果在iOS7 推出的網絡請求api。AF支持https,網絡數據請求,文件上傳,文件下載,監聽手機網絡狀態。AFHttpSessionManager 繼承 AFURLSessionManager 對網絡請求進行管理,使用AFURLRequestSerialization 對網絡請求進行封裝,使用AFURLReponseSerialization 響應體進行處理,使用AFSecurityPolicy 對服務器證書進行校驗。支持https協議,支持本地證書和服務器證書進行對比驗證,AF要求ios7或以上系統。AF數據傳遞主要使用block 和 notifacation的方式。
使用詳解
AFURLSessionManager 使用方法
1、請求服務器數據
2、上傳數據
3、多線程下載數據
AFHttpSessionManager 使用方法
1、post
2、get
3、上傳
AFSecurityPolicy
服務器和客戶端都生成相應的證書之後,iOS項目將服務器端的證書保存導入到項目中。接著AFN根據項目中的服務器的證書來進行驗證。
AFSecurityPolicy對服務器的驗證,保證訪問服務器的安全性。(這裏牽涉到Https和Http的不同,以及不同的驗證方式,請求有何不同。)
證書的驗證模式 AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
- AFSSLPinningModeNone
不做任何驗證,只要服務器返回了證書就通過
- AFSSLPinningModePublicKey
只驗證公鑰部分,只要公鑰部分一致就驗證通過,如圖所示,紅色框起來的部分只要一致就通過
- AFSSLPinningModeCertificate
除了公鑰外,其他能容也要一致才能通過驗證。
AFURLSessionManager
AFURLSessionManager管理所有的請求,session 設置了NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate 實現證書合法性校驗,數據傳輸進度檢測,數據請求成功或失敗的回調。
使用runtime 用af_supend 替換 suspend,用af_resume 替換了resume 當調用這兩個方法的時候往上層發送通知AFNetworkingTaskDidSuspendNotification AFNetworkingTaskDidResumeNotification
AFNetworking 3.0 使用詳解 和 源碼解析實現原理