1. 程式人生 > >解讀 AFNetwork 3.x原始碼 與 AFNetwork 2.x

解讀 AFNetwork 3.x原始碼 與 AFNetwork 2.x

對比AFNetwork 3.x 與 AFNetwork 2.x

AFNetworking支援HTTP請求和基於REST的網路服務(包括GET、POST、 PUT以及DELETE等),支援ARC。AFNetworking專案中還包含一些列單元測試。

AFNetworking 2.0開始使用NSURLConnection的基礎API ,以及較新基於NSURLSession的API的選項。 AFNetworking 3.0現已完全基於NSURLSession的API,刪除了了對 NSURLConnection的封裝內容

這是因為NSURLSession能夠完全替代NSURLConnection,並且具有很多優點:

  • 支援後臺執行的網路任務
  • 暫停、停止、重啟網路任務,不需要自己封裝NSOperation
  • 支援斷點續傳,非同步下載
  • 支援上傳,非同步上傳
  • 獲取下載、上傳的進度

注意:

3.0版本最低支援版本是從iOS7

1.廢棄的類

廢棄對NSURLConnection的支援
被刪除的類:

  • AFURLConnectionOperation
  • AFHTTPRequestOperation
  • AFHTTPRequestOperationManager

用以替代的是下面的類:

  • AFURLSessionManager
  • AFHTTPSessionManager

進行修改的類:

  • UIImageView+AFNetworking
  • UIWebView+AFNetworking.h
  • UIButton+AFNetworking.h

如果你之前的開發是基於AFHTTPRequestOperationManager的網路請求現在你應該轉到AFHTTPSessionManager下去進行

UIKit的遷移

圖片下載已經被重構,以遵循AlamofireImage架構與新的AFImageDownloader類。這個類的圖片下載職責的代理人是UIButton與UIImageView的類目,並且提供了一些方法,在必要時可以自定義。類別中,下載遠端圖片的實際方法沒有改變。

UIWebView的類目被重構為使用AFHTTPSessionManager作為其網路請求。

UIAlertView的類目被廢棄
從AFNetworking 3.0後UIAlertView的類目因過時而被廢棄。並沒有提供UIAlertController類目的計劃,因為這是應用程式應處理的邏輯,而不是這個庫。

下面進行新舊對比:

AFNetwork 2.x

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
  //設定網路請求超時時間
  [manager.requestSerializer willChangeValueForKey:@"timeoutInterval"];
  manager.requestSerializer.timeoutInterval = 30.0f;
  [manager.requestSerializer didChangeValueForKey:@"timeoutInterval"];
  [manager.requestSerializer setValue:@"application/x-www-form-urlencoded;" forHTTPHeaderField:@"Content-Type"];
  [self addHeaderParams:manager];
  manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"text/html",nil];
  [manager POST:self.requestURL
     parameters:self.requestParams
        success:^(AFHTTPRequestOperation *operation, id responseObject) {

           (@"success-POST:%@",responseObject);

        }
        failure:^(AFHTTPRequestOperation *operation, NSError *error) {
          DebugLog(@"failurePOST:%@",error.description)             
        }];

AFNetworking 3.x

   AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    [manager.requestSerializer willChangeValueForKey:@"timeoutInterval"];
    manager.requestSerializer.timeoutInterval = 30.0f;//30.0f
    [manager.requestSerializer didChangeValueForKey:@"timeoutInterval"];
    [manager.requestSerializer setValue:@"application/x-www-form-urlencoded;" forHTTPHeaderField:@"Content-Type"];
    [self addHeaderParams:manager];    
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"text/html",nil];

    [manager POST:self.requestURL parameters:self.requestParams progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {

    NSLog(@"success-POST:%@",responseObject);

} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

}];

即:每次開啟一個網路請求時,首先新建一個AFHTTPSessionManager,然後將相關的requestSerializer和reponseSerializer賦值;最後發起相應的GET/POST等請求。

如果是直接採用NSURLSession來請求網路,寫法如下:

NSURLSession *session =  [NSURLSession 
    sessionWithConfiguration:
    [NSURLSessionConfiguration defaultSessionConfiguration]
     delegate:nil
      delegateQueue:[NSOperationQueue mainQueue]];

      NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
      completionHandler:completionHandler];

    [dataTask resume];

即:新建一個Session(多個請求要用共享的SessionManager/Session),然後新建task,啟用task,完成網路請求。

共享原因:
共享的Session將會複用TCP的連線,而每次都新建Session的操作將導致每次的網路請求都開啟一個TCP的三次握手,共享會提升網路速度

AFNetworking 3.x 提供的post方法:

  [manager POST: parameters: constructingBodyWithBlock: progress: success: failure:]

  [manager POST: parameters: progress: success: failure:]

不建議使用的方法:

 [manager POST: parameters: success: failure:];
 [manager POST: parameters: constructingBodyWithBlock: success: failure:]

2. AFNetworking快取

AFNetworking實際上使用了兩個獨立的快取機制:

(1)AFImagecache:一個提供圖片記憶體快取的類,2.x時繼承自NSCache,3.x不再使用NSCache。AFImagecache3.x之前存在於UIImageView+AFNetwork,之後存在於AFAutoPurgingImageCache中。
(2)NSURLCache:仍使用原生快取機制:NSURLCache。NSURLConnection’s預設的URL快取機制,用於儲存NSURLResponse物件:一個預設快取在記憶體,通過配置可以快取到磁碟的類。NSURLCache對每個NSURLRequest物件都會遵守快取策略(NSURLRequestCachePolicy)。

注意:NSCache與NSURLCache沒有任何關係

3.0之前的快取方法:存在於AFURLConnectionOperation類檔案中。

- (void)setCacheResponseBlock:(NSCachedURLResponse * (^)(NSURLConnection *connection, NSCachedURLResponse *cachedResponse))block;

3.0之後:在類AFURLSessionManager中

- (void)setDataTaskWillCacheResponseBlock:(nullable NSCachedURLResponse * (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSCachedURLResponse *proposedResponse))block;

描述:

Sets a block to be executed to determine the caching behavior of a data task, as handled by the NSURLSessionDataDelegate method URLSession:dataTask:willCacheResponse:completionHandler:.
@param block A block object to be executed to determine the caching behavior of a data task. The block returns the response to cache, and takes three arguments: the session, the data task, and the proposed cached URL response.
*/

蘋果系統快取儲存策略:

    {   
    NSURLCacheStorageAllowed,  //預設,可以存在記憶體(重啟裝置清除),可以儲存磁碟(程式碼清除)
    NSURLCacheStorageAllowedInMemoryOnly,
    NSURLCacheStorageNotAllowed,
    } NSURLCacheStoragePolicy;

請求快取策略:

{
  NSURLRequestUseProtocolCachePolicy = 0, //預設策略
  NSURLRequestReloadIgnoringLocalCacheData = 1,//忽略本地快取,從源載入
  NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, // 忽略本地&伺服器快取,從源載入
  NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,
  NSURLRequestReturnCacheDataElseLoad = 2,  //先從快取載入,如果沒有快取,從源載入
  NSURLRequestReturnCacheDataDontLoad = 3,  //離線模式,載入快取資料(無論是否過期),不從源載入
  NSURLRequestReloadRevalidatingCacheData = 5 // 存在的快取資料先確認有效性,無效的話從源載入 
};
 typedef NSUInteger NSURLRequestCachePolicy;

清除所有的URL快取Response:

[[NSURLCache sharedURLCache] removeAllCachedResponses];