AFNetworking 概述(一)

afnetworking-logo

Blog: Dravenesshtml

關注倉庫,及時得到更新:iOS-Source-Code-Analyzegit

在這一系列的文章中,我會對 AFNetworking 的源代碼進行分析,深刻了解一下它是如何構建的,如何在平常中完成發送 HTTP 請求、構建網絡層這一任務。github

AFNetworking 是現在 iOS 開發中不可缺乏的組件之一。它的 github 配置上是以下介紹的:json

Perhaps the most important feature of all, however, is the amazing community of developers who use and contribute to AFNetworking every day. AFNetworking powers some of the most popular and critically-acclaimed apps on the iPhone, iPad, and Mac.安全

能夠說使用 AFNetworking 的工程師構成的社區才使得它變得很是重要。服務器

概述

咱們今天是來深刻研究一下這個與咱們平常開發密切相關的框架是如何實現的。網絡

這是我對 AFNetworking 整個架構的理解,隨後一系列的文章也會逐步分析這些模塊。session

afnetworking-arch

在這篇文章中,咱們有兩個問題須要瞭解:架構

  1. 如何使用 NSURLSession 發出 HTTP 請求app

  2. 如何使用 AFNetworking 發出 HTTP 請求

NSURLSession

NSURLSession 以及與它相關的類爲咱們提供了下載內容的 API,這個 API 提供了一系列的代理方法來支持身份認證,而且支持後臺下載。

使用 NSURLSession 來進行 HTTP 請求而且得到數據總共有五個步驟:

  1. 實例化一個 NSURLRequest/NSMutableURLRequest,設置 URL

  2. 經過 - sharedSession 方法獲取 NSURLSession

  3. 在 session 上調用 - dataTaskWithRequest:completionHandler: 方法返回一個 NSURLSessionDataTask

  4. 向 data task 發送消息 - resume,開始執行這個任務

  5. 在 completionHandler 中將數據編碼,返回字符串

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[[NSURL alloc] initWithString:@"https://github.com"]];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
                                       completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                                           NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                                           NSLog(@"%@", dataStr);
                                       }];
[task resume];

這一段代碼能夠說是使用 NSURLSession 發送請求最簡單的一段代碼了,當你運行這段代碼會在控制檯看到一坨 github 首頁的 html。

<!DOCTYPE html>
<html lang="en" class="">
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# object: http://ogp.me/ns/object# article: http://ogp.me/ns/article# profile: http://ogp.me/ns/profile#">
    <meta charset='utf-8'>
        ...
    </head>
    ...
</html>

AFNetworking

AFNetworking 的使用也是比較簡單的,使用它來發出 HTTP 請求有兩個步驟

  1. 以服務器的主機地址或者域名生成一個 AFHTTPSessionManager 的實例

  2. 調用 - GET:parameters:progress:success:failure: 方法

AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithBaseURL:[[NSURL alloc] initWithString:@"hostname"]];
[manager GET:@"relative_url" parameters:nil progress:nil
    success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"%@" ,responseObject);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"%@", error);
    }];

注意:在 iOS9 中,蘋果默認全局 HTTPs,若是你要發送不安全的 HTTP 請求,須要在 info.plist 中加入以下鍵值對才能發出不安全的 HTTP 請求

afnetworking-plist

還有一件事情是要注意的是,AFNetworking 默認接收 json 格式的響應(由於這是在 iOS 平臺上的框架,通常不須要 text/html),若是想要返回 html,須要設置 acceptableContentTypes

AFNetworking 的調用棧

在這一節中咱們要分析一下在上面兩個方法的調用棧,首先來看的是 AFHTTPSessionManager 的初始化方法 - initWithBaseURL:

- [AFHTTPSessionManager initWithBaseURL:]
    - [AFHTTPSessionManager initWithBaseURL:sessionConfiguration:]
        - [AFURLSessionManager initWithSessionConfiguration:]
            - [NSURLSession sessionWithConfiguration:delegate:delegateQueue:]
            - [AFJSONResponseSerializer serializer] // 負責序列化響應
            - [AFSecurityPolicy defaultPolicy] // 負責身份認證
            - [AFNetworkReachabilityManager sharedManager] // 查看網絡鏈接狀況
        - [AFHTTPRequestSerializer serializer] // 負責序列化請求
        - [AFJSONResponseSerializer serializer] // 負責序列化響應

從這個初始化方法的調用棧,咱們能夠很是清晰地瞭解這個框架的結構:

  • 其中 AFURLSessionManagerAFHTTPSessionManager 的父類

  • AFURLSessionManager 負責生成 NSURLSession 的實例,管理 AFSecurityPolicyAFNetworkReachabilityManager,來保證請求的安全和查看網絡鏈接狀況,它有一個 AFJSONResponseSerializer 的實例來序列化 HTTP 響應

  • AFHTTPSessionManager 有着本身的 AFHTTPRequestSerializerAFJSONResponseSerializer 來管理請求和響應的序列化,同時依賴父類提供的接口保證安全、監控網絡狀態,實現發出 HTTP 請求這一核心功能

初始化方法很好地揭示了 AFNetworking 整個框架的架構,接下來咱們要經過分析另外一個方法 - GET:parameters:process:success:failure: 的調用棧,看一下 HTTP 請求是如何發出的:

- [AFHTTPSessionManager GET:parameters:process:success:failure:]
    - [AFHTTPSessionManager dataTaskWithHTTPMethod:parameters:uploadProgress:downloadProgress:success:failure:] // 返回 NSURLSessionDataTask #1
        - [AFHTTPRequestSerializer requestWithMethod:URLString:parameters:error:] // 返回 NSMutableURLRequest
        - [AFURLSessionManager dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:] // 返回 NSURLSessionDataTask #2
            - [NSURLSession dataTaskWithRequest:] // 返回 NSURLSessionDataTask #3
            - [AFURLSessionManager addDelegateForDataTask:uploadProgress:downloadProgress:completionHandler:]
                - [AFURLSessionManagerTaskDelegate init]
                - [AFURLSessionManager setDelegate:forTask:]
    - [NSURLSessionDataTask resume]

在這裏 #1 #2 #3 處返回的是同一個 data task,咱們能夠看到,在 #3 處調用的方法 - [NSURLSession dataTaskWithRequest:] 和只使用 NSURLSession 發出 HTTP 請求時調用的方法 - [NSURLSession dataTaskWithRequest:completionHandler:] 差很少。在這個地方返回 data task 以後,咱們再調用 - resume 方法執行請求,並在某些事件執行時通知代理 AFURLSessionManagerTaskDelegate

小結

AFNetworking 實際上只是對 NSURLSession 高度地封裝, 提供一些簡單易用的 API 方便咱們在 iOS 開發中發出網絡請求並在其上更快地構建網絡層組件並提供合理的接口.

到這裏,這一篇文章從上到下對 AFNetworking 是如何調用的進行了一個簡單的概述,我會在隨後的文章中會具體介紹 AFNetworking 中的每個模塊,瞭解它們是如何工做,而且如何合理地組織到一塊兒的。

關於其餘 AFNetworking 源代碼分析的其餘文章:

關注倉庫,及時得到更新:iOS-Source-Code-Analyze

Blog: Draveness

相關文章
相關標籤/搜索