美文网首页
AFNetworking源码解析

AFNetworking源码解析

作者: TaoGeNet | 来源:发表于2017-09-22 18:26 被阅读126次

    AFNetworking 网络请求使用

    天气网络请求

        AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]initWithBaseURL:[NSURL URLWithString:@"http://www.sojson.com"]];
        [manager GET:@"/open/api/weather/json.shtml" parameters:@{@"city":@"北京"} progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            NSLog(@"%@", responseObject);
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            NSLog(@"%@", error);
        }];
    

    从初始化AFHTTPSessionManager方法得到以下调用栈

    - [AFHTTPSessionManager initWithBaseURL:]
        - [AFHTTPSessionManager initWithBaseURL:sessionConfiguration:]
            - [AFURLSessionManager initWithSessionConfiguration:]
                - [NSURLSession sessionWithConfiguration:delegate:delegateQueue:]
                - [AFJSONResponseSerializer serializer] // 负责序列化响应
                - [AFSecurityPolicy defaultPolicy] // 负责身份认证
                - [AFNetworkReachabilityManager sharedManager] // 查看网络连接情况
            - [AFHTTPRequestSerializer serializer] // 负责序列化请求
            - [AFJSONResponseSerializer serializer] // 负责序列化响应
    

    可以看出AFHTTPSessionManager继承AFURLSessionManager
    针对于HTTP快速创建请求GET、POST等

    AFNetworking 整体框架

    af2.png

    查看 -GET:parameter:process:success:failure:调用栈

    - [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]
    

    AFURLSessionManager 介绍

     `AFURLSessionManager` creates and manages an `NSURLSession` object based on a specified `NSURLSessionConfiguration` object, which conforms to `<NSURLSessionTaskDelegate>`, `<NSURLSessionDataDelegate>`, `<NSURLSessionDownloadDelegate>`, and `<NSURLSessionDelegate>`.
    

    1.负责创建和管理NSURLSession
    2.管理NSURLSessionTask
    3.实现NSURLSession中各种代理协议
    4.引入AFSecurityPolicy保证请求的安全
    5.引入AFNetworkingReachabilityManager监控网络状态

    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];
    
        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;
    }
    

    AFURLSessionManager实例化后,创建NSURLSessionData实例,方法包括

    /**
     Creates an `NSURLSessionDataTask` with the specified request.
    
     @param request The HTTP request for the request.
     @param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any.
     */
    - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
                                completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject,  NSError * _Nullable error))completionHandler;
    
    /**
     Creates an `NSURLSessionDataTask` with the specified request.
    
     @param request The HTTP request for the request.
     @param uploadProgressBlock A block object to be executed when the upload progress is updated. Note this block is called on the session queue, not the main queue.
     @param downloadProgressBlock A block object to be executed when the download progress is updated. Note this block is called on the session queue, not the main queue.
     @param completionHandler A block object to be executed when the task finishes. This block has no return value and takes three arguments: the server response, the response object created by that serializer, and the error that occurred, if any.
     */
    - (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;
    

    具体的调用如下

    - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
                                completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
    {
        return [self dataTaskWithRequest:request uploadProgress:nil downloadProgress:nil completionHandler:completionHandler];
    }
    
    - (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 = [self.session dataTaskWithRequest:request];
        });
    
        [self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];
    
        return dataTask;
    }
    

    该方法中,AFURLSessionManager调用
    [AFURLSessionManager addDelegateForDataTask:uploadProgress:downloadProgress:completionHandler:] 该方法,将completionHandler uploadProgressBlock和downloadProgressBlock传入创建的AFURLSessionManagerTaskDelegate对象中并在相应事件发生时进行回调。
    该方法具体实现,处于AFURLSessionManager.M文件中

    - (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] init];
        delegate.manager = self;
        delegate.completionHandler = completionHandler;
    
        dataTask.taskDescription = self.taskDescriptionForSessionTasks;
        [self setDelegate:delegate forTask:dataTask];
    
        delegate.uploadProgressBlock = uploadProgressBlock;
        delegate.downloadProgressBlock = downloadProgressBlock;
    }
    

    通过调用 - [AFURLSessionManager setDelegate:forTask:]来设置代理:

    - (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
                forTask:(NSURLSessionTask *)task
    {
        NSParameterAssert(task);
        NSParameterAssert(delegate);
    
        [self.lock lock];
        self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
        [delegate setupProgressForTask:task];
        [self addNotificationObserverForTask:task];
        [self.lock unlock];
    }
    

    可以看出,AFURLSessionManager通过字典mutableTaskDelegatesKeyedByTaskIdentifier 来存储和管理每个NSURLSessionTask,以taskIdentifier为key值。

    查看AFURLSessionManager中实现的各种代理包括:

    NSURLSessionDelegate
    NSURLSessionTaskDelegate
    NSURLSessionDataDelegate
    NSURLSessionDownDelegate

    将NSURLSession的代理指向AFURLSessionManager的代码

    self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
    

    NSURLSessionDelegate 对应的方法

    /*
     * Messages related to the URL session as a whole
     */
    @protocol NSURLSessionDelegate <NSObject>
    @optional
    
    /* The last message a session receives.  A session will only become
     * invalid because of a systemic error or when it has been
     * explicitly invalidated, in which case the error parameter will be nil.
     */
    - (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable NSError *)error;
    
    /* If implemented, when a connection level authentication challenge
     * has occurred, this delegate will be given the opportunity to
     * provide authentication credentials to the underlying
     * connection. Some types of authentication will apply to more than
     * one request on a given connection to a server (SSL Server Trust
     * challenges).  If this delegate message is not implemented, the 
     * behavior will be to use the default handling, which may involve user
     * interaction. 
     */
    - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
                                                 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler;
    
    /* If an application has received an
     * -application:handleEventsForBackgroundURLSession:completionHandler:
     * message, the session delegate will receive this message to indicate
     * that all messages previously enqueued for this session have been
     * delivered.  At this time it is safe to invoke the previously stored
     * completion handler, or to begin any internal updates that will
     * result in invoking the completion handler.
     */
    - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session API_AVAILABLE(ios(7.0), watchos(2.0), tvos(9.0)) API_UNAVAILABLE(macos);
    
    

    通过实现该代理,再执行AFURLSessionManager实现的Block。

    例如AFURLSessionManager 暴露的方法

    /**
     Sets a block to be executed when the managed session becomes invalid, as handled by the `NSURLSessionDelegate` method `URLSession:didBecomeInvalidWithError:`.
    
     @param block A block object to be executed when the managed session becomes invalid. The block has no return value, and takes two arguments: the session, and the error related to the cause of invalidation.
     */
    - (void)setSessionDidBecomeInvalidBlock:(nullable void (^)(NSURLSession *session, NSError *error))block;
    
    /**
     Sets a block to be executed when a connection level authentication challenge has occurred, as handled by the `NSURLSessionDelegate` method `URLSession:didReceiveChallenge:completionHandler:`.
    
     @param block A block object to be executed when a connection level authentication challenge has occurred. The block returns the disposition of the authentication challenge, and takes three arguments: the session, the authentication challenge, and a pointer to the credential that should be used to resolve the challenge.
     */
    - (void)setSessionDidReceiveAuthenticationChallengeBlock:(nullable NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * _Nullable __autoreleasing * _Nullable credential))block;
    

    AFURLSession中NSURLSessionDelegate的实现

    #pragma mark - NSURLSessionDelegate
    
    - (void)URLSession:(NSURLSession *)session
    didBecomeInvalidWithError:(NSError *)error
    {
        if (self.sessionDidBecomeInvalid) {
            self.sessionDidBecomeInvalid(session, error);
        }
    
        [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDidInvalidateNotification object:session];
    }
    

    AFURLSessionManager 中AFURLSessionManagerTaskDelegate代理管理task进度并在结束时进行回调。

    主要方法

    - (void)setupProgressForTask:(NSURLSessionTask *)task
    

    该方法的主要作用
    1.设置uploadProgress,downloadProgress回调代码
    2.添加KVO 对task中NSProgress中属性进行键值观测

    AFURLSessionManagerTaskDelegate 中实现的 NSURLSessionTaskDelegate代理方法

    - (void)URLSession:(__unused NSURLSession *)session
                  task:(NSURLSessionTask *)task
    didCompleteWithError:(NSError *)error
    

    具体实现可参照该框架

    - (void)URLSession:(__unused NSURLSession *)session
                  task:(NSURLSessionTask *)task
    didCompleteWithError:(NSError *)error  
    {
        #1:获取数据, 存储 `responseSerializer` 和 `downloadFileURL`
        if (error) {
            #2:在存在错误时调用 `completionHandler`
        } else {
            #3:调用 `completionHandler`
        }
    }
    

    AFNetWorking 总结

    AFURLSessionManager是对NSURLSession的封装
    它通过- [AFURLSessionManager dataTaskWithRequest:completionHandler:]等接口创建NSURLSessionDataTask的实例
    持有一个字典mutableTaskDelegatesKeyedByTaskIdentifier管理这些data task 实例
    引入AFURLSessionManagerTaskDelegate来对传入的uploadProgressBlock downloadProgressBlock completionHandler 在合适的时间进行调用
    实现了全部的代理方法来提供block接口
    通过方法调用在data task 状态改变时,发出通知

    相关文章

      网友评论

          本文标题:AFNetworking源码解析

          本文链接:https://www.haomeiwen.com/subject/jsugsxtx.html