標籤:
源地址:http://fann.im/blog/2012/08/21/afnetworking-notes/
- 這篇筆記是在 AFN v0.10.1 時候寫的,AFN v1.0 以後加入了不少新東西,比如 SSL 支援,不過整體結構沒有變化。
- 後續跟進了一篇 AFNetworking Notes 2
來自 @mattt 對 AFN 的介紹:Everybody Loves AFNetworking And So Can You!. 學習 AFN,簡單記錄一下以加深自己理解。
AFN 的基礎部分是 AFURLConnectionOperation,一個 NSOperation subclass,實現了 NSURLConnection 相關的 delegate+blocks,網路部分是由 NSURLConnection 完成,然後利用 NSOperation 的 state (isReady→isExecuting→isFinished) 變化來進行網路控制。網路請求是在一個指定的線程(networkRequestThread)完成。
AFURLConnectionOperation 是一個很純粹的網路請求 operation,可以對他進行 start/cancel/pause/resume 操作,可以擷取對應的 NSURLRequest 和 NSURLResponse 資料。支援 NSInputStream/NSOutputStream,提供了 uploadPress 和 downloadProgress 以方便其他使用。
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://httpbin.org/ip"]];AFURLConnectionOperation *operation = [[AFURLConnectionOperation alloc] initWithRequest:request];operation.completionBlock = ^ { NSLog(@"Complete: %@", operation.responseString);};[operation start];
插播:@mattt 在 NSHipster 裡有一篇 NSOperation 詳細介紹了 NSOperation 的 state、priority、dependency 等,對理解 AFURLConnectionOperation 很有協助。
理解了 AFURLConnectionOperation 再看 AFHTTPRequestOperation 就簡單很多。AFHTTPRequestOperation 是 AFURLConnectionOperation 的子類,針對 HTTP+HTTPS 協議做了一層封裝,比如 statusCode、Content-Type 等,添加了請求成功和失敗的回調 block,提供了 addAcceptableContentTypes: 以方便上層使用。
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://httpbin.org/robots.txt"]];AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"Success: %@", operation.responseString);} failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"Failure: %@", error);}];[operation start];
AFJSONRequestOperation 是 AFHTTPRequestOperation 的子類,針對 JSON 類型請求做了特殊處理,在有了 AFHTTPRequestOperation+AFURLConnectionOperation 的基礎工作後,AFJSONRequestOperation 已經非常方便直接使用了。指定 acceptableContentTypes: 以支援 JSON,responseJSON 直接返回已經解析好的 JSON 資料對象。下載到 JSON 資料後在一單獨線程 queue(json_request_operation_processing_queue)對 JSON 資料進行解析處理,處理完成後由主線程回調 success block。
AFN 的 JSON encode/decode 處理做的非常巧妙,現在有很多 JSON 解析庫,第三方的 JSONKit、SBJSON 等,iOS 5+ 內建的 NSJSONSerialization,不同的項目可能會因為不同的需求而用不同的庫,AFN 就封裝了一個 AFJSONUtilities,提供 AFJSONEncode 和 AFJSONDecode 兩個方法,通過 NSClassFromString 和 NSSelectorFromString 來尋找項目中使用的 JSON 庫然後進行 encode/decode。
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://httpbin.org/get"]];AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { NSLog(@"Success :%@", JSON); } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) { NSLog(@"Failure: %@", error); }];[operation start];
AFXMLRequestOperation/AFPropertyListRequestOperation/AFImageRequestOperation 和 AFJSONRequestOperation 類似,針對 XML、Plist、image 類型請求做了一些處理。其中 AFImageRequestOperation 額外有一個 imageProcessingBlock,取到圖片後可以在一個單獨線程 queque 對圖片進行處理,比如縮放、切圓角、圖片特效等,然後再交給 main_queue success block.
AFN 還提供了一個 UIImageView+AFNetworking category,可以用 setImageWithURL: 來設定圖片。這個 cagetory 和 SDWebImage 類似但更簡單一些,圖片下載由 AFN 完成,圖片緩衝由 NSCache 處理。
直接用上面這些已經可以方便的做網路請求,AFN 在這些基礎上還提供了一個 AFHTTPClient,把 HTTP 要求的 Headers、User-Agent 等再次封裝,方便使用。AFHTTPClient 是一個單例,對請求參數做了 URL 編碼;維護一個 NSOperationQueue,不同的請求產生各自的 AFHTTPRequestOperation 然後 enqueueHTTPRequestOperation: 添加的隊列順序執行;registerHTTPOperationClass: 方法用來註冊上面的 JSON/XML/Plist/image operation,拿到請求結果後交給對應的 operation 處理。AFHTTPClient 還針對 GET/POST/HEAD/PUT/DELETE 等不同的請求做了不同的 URL 參數和 Headers 處理,包括 multipart/form-data 類型。
AFHTTPClient 支援大量新增 operations,產生一個 batchedOperation,把所有 operations 作為 batchedOperation 的 dependency,再依次把所有 operations 和 batchedOperation 都添加到 operationQueue,這樣每一個 operation 完成後都可以做一個 progressBlock 來返回當前已完成的 operations 數和總數,等所有 operations 都完成後會做 batchedOperation 的 completionBlock,就可以在這一批 operations 都完成後做一些善後處理。
AFHTTPClient 提倡對同一應用(同一 baseURL)的網路請求封裝自己的 HTTPClient 子類,這樣會方便很多。參考 WBKHTTPClient.
AFN 還提供了很多模組,可以很方便的和 AFN 整合做一些工作,比如 OAuth,Amazon S3 等,詳見 AFNetworking-Extensions.
AFN 作者 @mattt 做東西很有自己一套思想在裡面,推薦 What I Learned From AFNetworking’s GitHub Issues,視頻。
iOS 8:【轉】AFNetworking 學習筆記