AFNetworking 原始碼閱讀

wxiubin發表於2017-12-19

AFNetworking 3.1.0

AFNetworking 主要的幾個類或協議:

  • AFURLSessionManager
  • AFHTTPSessionManager
  • AFNetworkReachabilityManager
  • AFSecurityPolicy
  • <AFURLRequestSerialization>
  • <AFURLResponseSerialization>

AFNetworking 原始碼閱讀

AFHTTPSessionManager

AFHTTPSessionManager 是我們使用 AFNetworking 框架最外層或者是可以直接使用的類,它對於框架核心類 AFURLSessionManager 進行了常用的封裝。比如設定 BaseURL 和請求序列化,AFHTTPSessionManager 重要的兩個屬性:

@property (readonly, nonatomic, strong, nullable) NSURL *baseURL;
@property (nonatomic, strong) AFHTTPRequestSerializer <AFURLRequestSerialization> * requestSerializer
複製程式碼

當傳送一個 GET 請求時,框架會依次呼叫以下三個方法:

[AFHTTPSessionManager GET:parameters:progress:success:failure:] [AFHTTPSessionManager dataTaskWithHTTPMethod:URLString:parameters:uploadProgress:downloadProgress:success:failure:] [AFURLSessionManager dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:]

第一個方法是 AFHTTPSessionManagerGETPOSTPUTPATCHDELETE 等請求做的一個封裝,它們的區別就是請求方法的不同,不同的請求會傳入不同的引數給第二個方法,在第二個方法中會對傳入的引數進行序列化。具體的序列化方法可以檢視 AFHTTPRequestSerializer。然後會把序列化之後的 NSMutableURLRequest 作為引數呼叫第三方方法,這時就進入了框架的核心類: AFURLSessionManager

AFURLSessionManager

AFURLSessionManager 持有一個 NSURLSession 型別的 session 屬性,並作為該屬性的 delegate,遵守實現了 NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate 四個代理方法,如果任何子類繼承重寫這些方法,都必須先呼叫父類的實現。

initWithSessionConfiguration:AFURLSessionManager 的指定初始化方法,並且在session 初始化指定為其的代理:

self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
複製程式碼

這樣的話當一個網路請求的資料有返回或者狀態被更改的時候,可以在代理方法中及時獲知。AFURLSessionManagersession 屬性可能會例項化多個 NSURLSessionDataTask 物件,但是 AFURLSessionManager 並不會直接維護它們,而是通過一個可變字典以 task.taskIdentifier 為 key 儲存一個私有類 AFURLSessionManagerTaskDelegate 的例項,這個例項會儲存這次網路請求的回撥、響應資料和進度,兩者是一對一的關係。當 AFURLSessionManager 所實現的協議方法被呼叫時,會及時更新 AFURLSessionManagerTaskDelegate 例項的資料。

在實現檔案中,框架還對 NSURLSessionDataTaskresumesuspend 方法進行了 Hook,在方法執行的時候傳送通知。

除此之外,AFURLSessionManager 還管理者 AFSecurityPolicyAFNetworkReachabilityManager,來保證請求的安全和檢視網路連線情況,它有一個 AFJSONResponseSerializer 的例項來序列化 HTTP 響應。

AFURLRequestSerialization 和 AFURLResponseSerialization

<AFURLRequestSerialization><AFURLResponseSerialization> 只是兩個協議,並且分別只有一個方法。

@protocol AFURLRequestSerialization <NSObject, NSSecureCoding, NSCopying>
- (nullable NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
                               withParameters:(nullable id)parameters
                                        error:(NSError * _Nullable __autoreleasing *)error NS_SWIFT_NOTHROW;
@end

@protocol AFURLResponseSerialization <NSObject, NSSecureCoding, NSCopying>
- (nullable id)responseObjectForResponse:(nullable NSURLResponse *)response
                           data:(nullable NSData *)data
                          error:(NSError * _Nullable __autoreleasing *)error NS_SWIFT_NOTHROW;
@end
複製程式碼

實現 <AFURLRequestSerialization> 協議的有 AFHTTPRequestSerializer 及其兩個子類: AFJSONRequestSerializerAFPropertyListRequestSerializerAFHTTPRequestSerializer除了實現協議之外還封裝了對 TTPHeader 和 HTTPBody 操作。

實現 <AFURLResponseSerialization> 協議的有 AFHTTPResponseSerializerAFJSONResponseSerializer 等數個子類。

AFHTTPResponseSerializer 有兩個屬性分來判斷接受的 StatusCode 和 ContentType:

@property (nonatomic, copy, nullable) NSIndexSet *acceptableStatusCodes;
@property (nonatomic, copy, nullable) NSSet <NSString *> *acceptableContentTypes
複製程式碼

AFJSONResponseSerializerAFHTTPSessionManager 類預設的響應序列化型別。

AFNetworkReachabilityManager

AFNetworkReachabilityManager 作用是監聽網路,是一個比較獨立的模組,可以拿出來單獨使用。

指定構造方法: initWithReachability:AFNetworkReachabilityManager 會持有這個 SCNetworkReachabilityRef 屬性。

呼叫 startMonitoring 開始監聽:

- (void)startMonitoring {
    // 先停止監聽
    [self stopMonitoring];
    // 不符合條件,直接返回
    if (!self.networkReachability) {
        return;
    }
    // 建立一個block作為 SCNetworkReachabilityContext 初始化的第二個引數,引數名:info 引數型別:無型別指標
    __weak __typeof(self)weakSelf = self;
    AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
        __strong __typeof(weakSelf)strongSelf = weakSelf;

        strongSelf.networkReachabilityStatus = status;
        if (strongSelf.networkReachabilityStatusBlock) {
            strongSelf.networkReachabilityStatusBlock(status);
        }

    };
    // 建立監聽上下文
    SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL};
    // 設定監聽回撥,回撥的是 AFNetworkReachabilityCallback 函式,並且callback會被作為引數一起回撥
    SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context);
    // 開始監聽
    SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
    // 獲取當前的網路狀態並回撥
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{
        SCNetworkReachabilityFlags flags;
        if (SCNetworkReachabilityGetFlags(self.networkReachability, &flags)) {
            AFPostReachabilityStatusChange(flags, callback);
        }
    });
}
複製程式碼

我的部落格:iosgg.cn/

相關文章