AFN3.0源碼解析

目錄結構

在這裏插入圖片描述

  1. NSURLSession
    這個目錄是封裝了http請求須要的代碼,其中AFURLSessionManager類主要處理http請求,AFHTTPSessionManager類是對其進行封裝留給用戶調用的上層接口。好比咱們平時的get,post請求就要用到該類,也是本文要分析的重點。html

  2. Reachability
    這個目錄是判斷網絡狀態的json

  3. Security
    https請求bash

  4. Serialization
    http請求和相應的配置網絡

  5. UIKit
    分類session

post請求過程

第一步:用戶建立單例

+ (instancetype)shareManager{
    static dispatch_once_t token;
    static HttpClientManager *instance = nil;
    _dispatch_once(&token, ^{
        instance = [[self alloc] init];
        [instance initSession];
    });
    return instance;
}

- (void)initSession{
    _sessionManger = [AFHTTPSessionManager manager];
    _sessionManger.requestSerializer = [AFJSONRequestSerializer serializer];//請求配置
    AFJSONResponseSerializer *response = [AFJSONResponseSerializer serializer];//相應配置
    response.removesKeysWithNullValues = YES;//當出現null值時候移除該鍵值對
    _sessionManger.responseSerializer =  response;
    _sessionManger.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"text/json", @"text/plain", @"text/html", nil];//相應配置

    _baseUrl = @"http:xxxxx/";//協議+域名+端口號(請求前綴)

}
複製代碼

[AFHTTPSessionManager manager]查看源代碼發現接下來調用一下代碼多線程

//1.(AFHTTPSessionManager類)
+ (instancetype)manager {
    return [[[self class] alloc] initWithBaseURL:nil];
}

//2.(AFHTTPSessionManager類)
- (instancetype)initWithBaseURL:(NSURL *)url {
    return [self initWithBaseURL:url sessionConfiguration:nil];
}

//3.(AFHTTPSessionManager類)
- (instancetype)initWithBaseURL:(NSURL *)url
           sessionConfiguration:(NSURLSessionConfiguration *)configuration
{
    self = [super initWithSessionConfiguration:configuration];//分析父類
    if (!self) {
        return nil;
    }

    // Ensure terminal slash for baseURL path, so that NSURL +URLWithString:relativeToURL: works as expected
    if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) {
        url = [url URLByAppendingPathComponent:@""];
    }

    self.baseURL = url;

    self.requestSerializer = [AFHTTPRequestSerializer serializer];
    self.responseSerializer = [AFJSONResponseSerializer serializer];

    return self;
}

//4.(AFURLSessionManager類)
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
    self = [super init];
    if (!self) {
        return nil;
    }

    if (!configuration) {
        configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    }

    self.sessionConfiguration = configuration;

    self.operationQueue = [[NSOperationQueue alloc] init];
    self.operationQueue.maxConcurrentOperationCount = 1;

    self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];//注意delegate = self,也就是說網絡請求的結果在AFURLSessionManager類裏

    self.responseSerializer = [AFJSONResponseSerializer serializer];

    self.securityPolicy = [AFSecurityPolicy defaultPolicy];

#if !TARGET_OS_WATCH
    self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];
#endif

    self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];

    self.lock = [[NSLock alloc] init];
    self.lock.name = AFURLSessionManagerLockName;

    [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
        for (NSURLSessionDataTask *task in dataTasks) {
            [self addDelegateForDataTask:task uploadProgress:nil downloadProgress:nil completionHandler:nil];
        }

        for (NSURLSessionUploadTask *uploadTask in uploadTasks) {
            [self addDelegateForUploadTask:uploadTask progress:nil completionHandler:nil];
        }

        for (NSURLSessionDownloadTask *downloadTask in downloadTasks) {
            [self addDelegateForDownloadTask:downloadTask progress:nil destination:nil completionHandler:nil];
        }
    }];

    return self;
}
複製代碼

已上是AFHTTPSessionManager初始化的分析app

第二步:用戶開始調用post方法

[_sessionManger POST:urlString parameters:dicM progress:nil
        success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            //請求成功
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            //error包含HTTP請求的錯誤碼,或者NSURLError錯誤碼(-1001,-1009等等)
    }];
複製代碼

查看源代碼調用過程以下async

1.(AFHTTPSessionManager類)
- (NSURLSessionDataTask *)POST:(NSString *)URLString
                    parameters:(id)parameters
                      progress:(void (^)(NSProgress * _Nonnull))uploadProgress
                       success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
                       failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
{
    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"POST" URLString:URLString parameters:parameters uploadProgress:uploadProgress downloadProgress:nil success:success failure:failure];//分析源代碼(回調已經向下傳遞)

    [dataTask resume];

    return dataTask;
}

2.(AFHTTPSessionManager類)
- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
                                       URLString:(NSString *)URLString
                                      parameters:(id)parameters
                                  uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress
                                downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress
                                         success:(void (^)(NSURLSessionDataTask *, id))success
                                         failure:(void (^)(NSURLSessionDataTask *, NSError *))failure
{
    NSError *serializationError = nil;
    NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];//請求配置
    if (serializationError) {
        if (failure) {
            dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
                failure(nil, serializationError);//請求配置失敗
            });
        }

        return nil;
    }

    __block NSURLSessionDataTask *dataTask = nil;
    //如下建立dataTask(向下分析源代碼)
    dataTask = [self dataTaskWithRequest:request
                          uploadProgress:uploadProgress
                        downloadProgress:downloadProgress
                       completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
                           //回調(最上層的回調要執行那麼就必須該completionHandler回調必須執行,也就是說completionHandler回調執行與否決定最上層的回調是否執行。咱們只要關心completionHandler回調便可)
        if (error) {
            if (failure) {
                failure(dataTask, error);
            }
        } else {
            if (success) {
                success(dataTask, responseObject);
            }
        }
    }];

    return dataTask;//返回dataTask
}

//3.(AFURLSessionManager類)
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
                               uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock
                             downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock
                            completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject,  NSError * _Nullable error))completionHandler {

    __block NSURLSessionDataTask *dataTask = nil;
    url_session_manager_create_task_safely(^{
        //建立dataTask
        dataTask = [self.session dataTaskWithRequest:request];
    });

    //addDelegate(completionHandler向下傳遞),向下分析源代碼
    [self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];

    return dataTask;
}

//4.(AFURLSessionManager類)
- (void)addDelegateForDataTask:(NSURLSessionDataTask *)dataTask
                uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock
              downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock
             completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
    AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:dataTask];
    delegate.manager = self;
    //將回調保存到AFURLSessionManagerTaskDelegate對象裏
    delegate.completionHandler = completionHandler;

    dataTask.taskDescription = self.taskDescriptionForSessionTasks;
    //傳入delegate對象,dataTask(向下分析源代碼)
    [self setDelegate:delegate forTask:dataTask];
    
    delegate.uploadProgressBlock = uploadProgressBlock;
    delegate.downloadProgressBlock = downloadProgressBlock;
}

//5.(AFURLSessionManager類)
- (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
            forTask:(NSURLSessionTask *)task
{
    NSParameterAssert(task);
    NSParameterAssert(delegate);

    //避免多線程訪問mutableTaskDelegatesKeyedByTaskIdentifier字典
    [self.lock lock];
    //將AFURLSessionManagerTaskDelegate對象存儲在
    //mutableTaskDelegatesKeyedByTaskIdentifier字典裏
    //AFURLSessionManagerTaskDelegate對象裏邊存着回調,如今又將該對象存在字典裏。並以task.taskIdentifier爲key
    self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
    [self addNotificationObserverForTask:task];
    [self.lock unlock];
}
複製代碼

通過以上分析知道最後將回調保存在了mutableTaskDelegatesKeyedByTaskIdentifier這個字典裏的AFURLSessionManagerTaskDelegate對象中。
而後通過resume後,開始發起post請求。請求的結果回調在AFURLSessionManager類中(上面初始化代碼可知)。post

第三步:請求結果回調

找到AFURLSessionManager類下的網絡請求結果代理方法ui

//1. (AFURLSessionManager類)
- (void)URLSession:(NSURLSession *)session
              task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
    //獲取該task對應的AFURLSessionManagerTaskDelegate對象,實際上就是從字典中取值(分析源代碼)
    AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];

    // delegate may be nil when completing a task in the background
    if (delegate) {
        //調用AFURLSessionManagerTaskDelegate對象中的URLSession: task: didCompleteWithError:方法(分析源代碼)
        [delegate URLSession:session task:task didCompleteWithError:error];

        //移除task,其實是從字典中移除(分析源代碼)
        [self removeDelegateForTask:task];
    }

   //完成回調,其實這裏咱們沒用到,因此不會進入
    if (self.taskDidComplete) {
        self.taskDidComplete(session, task, error);
    }
}

//2.(AFURLSessionManager類)
- (AFURLSessionManagerTaskDelegate *)delegateForTask:(NSURLSessionTask *)task {
    NSParameterAssert(task);

    AFURLSessionManagerTaskDelegate *delegate = nil;
    [self.lock lock];
    //根據task.taskIdentifier獲取字典中的AFURLSessionManagerTaskDelegate對象
    delegate = self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)];
    [self.lock unlock];

    return delegate;
}

//3. (AFURLSessionManager類)
- (void)removeDelegateForTask:(NSURLSessionTask *)task {
    NSParameterAssert(task);

    [self.lock lock];
    [self removeNotificationObserverForTask:task];
    //從字典中移除task.taskIdentifier對應的AFURLSessionManagerTaskDelegate對象
    [self.mutableTaskDelegatesKeyedByTaskIdentifier removeObjectForKey:@(task.taskIdentifier)];
    [self.lock unlock];
}

//4.(AFURLSessionManagerTaskDelegate類)
- (void)URLSession:(__unused NSURLSession *)session
              task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
    __strong AFURLSessionManager *manager = self.manager;

    __block id responseObject = nil;

    
    //建立空字典userInfo
    __block NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
    //userInfo保存responseSerializer
    userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = manager.responseSerializer;

    //Performance Improvement from #2672
    //獲取data
    NSData *data = nil;
    if (self.mutableData) {
        data = [self.mutableData copy];
        //We no longer need the reference, so nil it out to gain back some memory.
        self.mutableData = nil;
    }

    if (self.downloadFileURL) {
        //userInfo保存downloadFileURL
        userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self.downloadFileURL;
    } else if (data) {
        //userInfo保存data
        userInfo[AFNetworkingTaskDidCompleteResponseDataKey] = data;
    }

    if (error) {
        //有錯誤
        //userInfo保存error
        userInfo[AFNetworkingTaskDidCompleteErrorKey] = error;

        dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
            //若是沒有定義隊列就在主隊列回調
            if (self.completionHandler) {
                //self是AFURLSessionManagerTaskDelegate對象,通過以上分析,該對象中的completionHandler回調,便可觸發上層回調
                self.completionHandler(task.response, responseObject, error);
            }

            dispatch_async(dispatch_get_main_queue(), ^{
                //發送通知,將userInfo發出
                [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
            });
        });
    } else {
        //請求成功
        dispatch_async(url_session_manager_processing_queue(), ^{
            //定義serializationError
            NSError *serializationError = nil;
            //data解析爲json對象
            responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError];

            if (self.downloadFileURL) {
                //responseObject賦值
                responseObject = self.downloadFileURL;
            }

            if (responseObject) {
                //userInfo保存responseObject
                userInfo[AFNetworkingTaskDidCompleteSerializedResponseKey] = responseObject;
            }

            if (serializationError) {
                //userInfo保存serializationError
                userInfo[AFNetworkingTaskDidCompleteErrorKey] = serializationError;
            }

            dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
                //若是沒有定義回調隊列,就在主隊列回調
                if (self.completionHandler) {
                    //self是AFURLSessionManagerTaskDelegate對象,通過以上分析,該對象中的completionHandler回調,便可觸發上層回調
                    self.completionHandler(task.response, responseObject, serializationError);
                }

                dispatch_async(dispatch_get_main_queue(), ^{
                    //發送通知,將userInfo發出
                    [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
                });
            });
        });
    }
}

複製代碼

AFN請求過程梳理

首先咱們是初始化了AFHTTPSessionManager類(每每建立單例)初始化時候指定請求回調的代理是父類(AFURLSessionManager)。以後當咱們發出一個請求後,先建立一個AFURLSessionManagerTaskDelegate對象來保存請求結果回調。並把該對象放到一個全局字典中來保存(以task.taskIdentifier爲key),再啓動請求。當AFURLSessionManager類收到了請求結果後根據task.taskIdentifier從全局字典中取出當前請求的AFURLSessionManagerTaskDelegate對象。而後調用AFURLSessionManagerTaskDelegate的對象方法處理請求,完成回調。以後再從全局字典中移除該AFURLSessionManagerTaskDelegate對象。

AFN是怎樣來解決循環引用的

首先咱們用AFN時候每每是用單例,所以調用類不會直接持有該AFHTTPSessionManager對象。

該AFHTTPSessionManager對象持有block,該AFHTTPSessionManager對象持有全局字典,該全局字典持有AFURLSessionManagerTaskDelegate對象,該AFURLSessionManagerTaskDelegate對象持有block,這是一個循環引用。

當AFURLSessionManagerTaskDelegate對象block進行回調後,從全局字典中移除該對象。從而打破引用環。

相關文章
相關標籤/搜索