使用AFN時在自然不過的一件事了,正如在java中會使用httpClient。AFN3.0開始完全基于NSURLSession了,從此就告別了繁瑣的線程操作的一些東西,轉而更加關注于請求功能的實現。最近一段時間研究了下AFN3.0,得到一些淺薄的筆記,記錄下來。
0. 一句話總結AFN
- 基于NSURLSession的輕量級,用于發送異步請求(get,post,文件上傳,下載)的框架。
- 包含了對NSURLRequest的封裝,NURLResponse的處理,以及連接的創建、管理,https安全性的配置,網絡的監測,UIKit的擴展。
- AFN3.X版本僅僅基于NSURLSession,AFN2.X主流用法還是繼續NSURLConnection。3.X比2.X結構更加簡單清晰。
1. AFN 是什么
AFN是一個輕量級的框架,它將通用的客戶端與服務器的交互的操作封裝了起來,包括了請求的創建,請求操作的管理,響應的序列化,網絡指示器的監測,安全性,以及UI控件異步加載網絡數據的便捷擴展。
2. AFN3.X能干什么
- 發異步請求:
- 文件上傳
- 文件下載(小文件,大文件和斷點續傳等操作目前需要自己封裝)
- 網絡監聽
3.AFN包含什么
AFN3.X的主要功能模塊包括:NSURLRequest的構建,NSURLSessionTask的創建和管理,進度的監測回調,結果的回調,響應的序列化處理
- AFN3.X
+ AFURLSessionManager
*工廠模式創建Task
*Task綁定TaskDelegate
*session代理回調,回調TaskDelegate響應回調
+ AFURLSessionManagerTaskDelegate
*KVO監測進度,并回調
*結果回調
+ AFHTTPSessionManager(繼承前者封裝了常用的 HTTP 方法)
* GET
* POST
* POST constructBody
+ AFURLRequestSerialization 請求的數據格式/默認是二進制的
*requestWithMethod
*multipartFormRequestWithMethod
* requestBySerializingRequest
+AFJSONRequestSerializer
* requestBySerializingRequest
+AFPropertyListRequestSerializer
* requestBySerializingRequest
+ AFURLResponseSerialization :響應的數據格式/默認是JSON格式
+ AFSecurityPolicy
+ AFNetworkReachabilityManager
- AFHTTPSessionManager的get方法基于NSURLSessionDataTask
- AFHTTPSessionManager的post方法基于NSURLSessionDataTask
- AFHTTPSessionManager的postconstruct方法基于 NSURLSessionUpLoadTask
- NSURLSessionDownLoadTask的封裝可以自己實現
4. AFN3.X的功能實現流程
根據請求參數創建請求——發送請求——響應處理
- 輸入:NSURLRequest,NSMutableURLRequest,
NSURLSession,NSOperation,NSOperationQueue - 輸出data,序列化的對象
- KVO監測下載和上傳的進度
- AFHTTPSessionManager get方法沒有封裝DownLoadTask,需要手動實現
- 上傳使用的是:uploadTaskWithStreamedRequest ,上傳的body使用的
是request.HTTPBodyStream
1)請求的序列化
目的:根據輸入的URL,參數字典,上傳數據(可選),構造NSURLRequest。
功能:默認構造為application/x-www-form-urlencoded
body類型的數據。get直接拼接URL,post作為請求體。
子類可以構造application/json
和application/x-plist
請求數據。設置為httpbodyData。
上傳數據形式為multipart/form-data; boundary=XXXX
,設置的是httpbodystream
原生沒有提供 僅僅上傳單個文件,和純文本body形式的API。但是話說回來,這兩種并不常用。
實現:兩個關鍵的方法構造請求:
- requestWithMethod:URLString: parameters:error:
此方法調用協議方法requestBySerializingRequest: withParameters:error:
- multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:error:
前者設置的是httpBody
后者設置是httpBodystream
具體實現細節:待續
2)響應的反序列化
目的:根據得到的NSURLResponse和body data轉化為所需要的數據類型。
功能: responseObjectForResponse:response data:error:
方法 得到感興趣的數據類型(id )responseObject
:
默認為data,json形式往往為NSDictionary。json的序列化可以設置是否去除null value。沒有提供responseString的功能,需要自己轉化。
響應默認為json處理形式,響應非json的話一定需要顯示的設置為AFURLResponseSerialization
類型
3)請求的創建,管理,維護
目的:發送請求,得到響應,處理好進度的回調,請求成功,失敗的回調
實現:
GET:parameters: progress:success:failure:
POST:parameters: progress:success:failure:
會調用
dataTaskWithHTTPMethod:URLString:parameters:uploadProgress:downloadProgress: success:failure:
然后調用
dataTaskWithRequest: uploadProgress: downloadProgress: completionHandler
(這是工廠方法創建Task的其中之一)
之后
調用
addDelegateForDataTask:uploadProgress: downloadProgress: completionHandler
在這里創建一個自定義的taskDelegate對象,將參數賦值給它。taskDelegate和Task是一一對應的,Task的進度檢測,結果的回調完全都是在taskDelegate中進行。
再調用
setDelegate:forTask:
這個方法是線程安全的,加上鎖的,功能:把delegate放入一個字典中做記錄,設置delegate的進度指示,KVO方法監測task的 countOfBytesReceived, countOfBytesExpectedToReceive等屬性
Session的代理方法在manager中調用:
manager中每一個代理方法都定義了一個block。調用相應代理方法的時候如果有相應的block就會回調。但是實際上,定義的get和post等方法并未使用。
反而,在代理方法中
調用
delegateForTask:
方法(加鎖的操作)根據task取得相應的taskDelegate然后回調相應的taskDelegate的方法。
taskDelegate中,KVO回調方法會實時監測進度并回調響應的block
在taskDelegate的 URLSession:task:didCompleteWithError:
中
獲取到之前拼接的data,根據序列化得到responseObject,response直接取task的屬性
然后回調 completionHandler block并發送相應通知。如果不設置 manager.completionQueue,就在main_queue中回調。
最后掃尾工作:移除taskDelegate的KVO和task的通知,保存task和taskDelegate的字典中移除(這個操作也需要加鎖)
POST:parameters: constructingBodyWithBlock:progress:success:failure:
調用
uploadTaskWithStreamedRequest:progress:uploadProgressBlock completionHandler:
之后的流程類似
progress回調是在sessionQueue中回調,不是在mainQueue
5.常用的封裝
待續
6.需要的背景知識
1)NSURLSession簡介
- NSURLSession的創建需要指定模式,代理,和代理的線程隊列
- NSURLSession的提供了豐富的構建task的方法,使用block的話就不會回調代理了
- NSURLSessionTask提供了開啟,中斷,取消的操作,狀態,發送接收數據的屬性,request,response,error屬性,沒有data屬性
使用代理的話,需要把data疊加 - NSURLSessionDelegate:session狀態的代理回調
- NSURLSessionDataDelegate: dataTask的方法回調
- NSURLSessionTaskDelegate:只要是TASK的方法回調
- NSURLSessionDownLoadTask:downLoadTask的方法回調