美文网首页iOS重修
iOS网络——AFNetworking AFHttpSessio

iOS网络——AFNetworking AFHttpSessio

作者: WWWWDotPNG | 来源:发表于2017-11-08 17:49 被阅读217次

    你要知道的NSURLSession都在这里

    转载请注明出处 http://www.jianshu.com/p/af80101b0513

    本系列文章主要讲解iOS中网络请求类NSURLSession的使用方法进行详解,同时也会以此为扩展,讲解SDWebImage中图片下载功能的源码分析,讲解AFNetworking相关源码分析。本系列文章主要分为以下几篇进行讲解,读者可按需查阅。

    AFNetworking AFHTTPSessionManager源码解析

    前一篇文章我们讲解了AFURLSessionManager的源码,最后还给了一个只使用AFURLSessionManager来创建NSURLSessionDataTaskNSURLSessionDownloadTask的栗子,但是发现创建下载任务真的很简单了,只需要传入要下载文件的NSURL对象,在传入几个回调块就能将文件下载到指定的目录中,并且可以监控下载进度,真的很方便,但NSURLSessionDataTask创建的任务默认是GET请求,如果需要其他如POST请求还需要修改request就显得有些麻烦了,今天要介绍的AFHTTPSessionManager就是继承自AFURLSessionManager,通过名称就知道这个类为HTTP访问提供了更加便捷的方法。

    直接看头文件的声明源码:

    //继承自AFURLSessionManager类
    @interface AFHTTPSessionManager : AFURLSessionManager <NSSecureCoding, NSCopying>
    
    //网络请求要访问的URL
    @property (readonly, nonatomic, strong, nullable) NSURL *baseURL;
    
    //请求序列化
    @property (nonatomic, strong) AFHTTPRequestSerializer <AFURLRequestSerialization> * requestSerializer;
    
    //响应序列化
    @property (nonatomic, strong) AFHTTPResponseSerializer <AFURLResponseSerialization> * responseSerializer;
    
    ///-------------------------------
    /// @name Managing Security Policy
    ///-------------------------------
    
    //安全策略
    @property (nonatomic, strong) AFSecurityPolicy *securityPolicy;
    
    ///---------------------
    /// @name Initialization
    ///---------------------
    
    //类方法返回一个AFHTTPSessionManager对象,不是单例,每次调用都重新创建
    + (instancetype)manager;
    
    //构造函数
    - (instancetype)initWithBaseURL:(nullable NSURL *)url;
    
    //构造函数
    - (instancetype)initWithBaseURL:(nullable NSURL *)url
               sessionConfiguration:(nullable NSURLSessionConfiguration *)configuration NS_DESIGNATED_INITIALIZER;
    
    ///---------------------------
    /// @name Making HTTP Requests
    ///---------------------------
    
    //获取一个GET请求
    - (nullable NSURLSessionDataTask *)GET:(NSString *)URLString
                       parameters:(nullable id)parameters
                          success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                          failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE;
    
    
    //获取一个GET请求
    - (nullable NSURLSessionDataTask *)GET:(NSString *)URLString
                                parameters:(nullable id)parameters
                                  progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress
                                   success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                                   failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
    
    //获取一个HEAD请求
    - (nullable NSURLSessionDataTask *)HEAD:(NSString *)URLString
                        parameters:(nullable id)parameters
                           success:(nullable void (^)(NSURLSessionDataTask *task))success
                           failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
    
    //获取一个POST请求
    - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
                        parameters:(nullable id)parameters
                           success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                           failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE;
    
    //获取一个POST请求
    - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
                                 parameters:(nullable id)parameters
                                   progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
                                    success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                                    failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
    
    //获取一个POST请求
    - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
                        parameters:(nullable id)parameters
         constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block
                           success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                           failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE;
    
    //获取一个POST请求
    - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
                                 parameters:(nullable id)parameters
                  constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block
                                   progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
                                    success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                                    failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
    
    //获取一个PUT请求
    - (nullable NSURLSessionDataTask *)PUT:(NSString *)URLString
                       parameters:(nullable id)parameters
                          success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                          failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
    
    //获取一个PATCH请求
    - (nullable NSURLSessionDataTask *)PATCH:(NSString *)URLString
                         parameters:(nullable id)parameters
                            success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                            failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
    
    //获取一个DELETE请求
    - (nullable NSURLSessionDataTask *)DELETE:(NSString *)URLString
                          parameters:(nullable id)parameters
                             success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                             failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
    
    @end
    

    AFHTTPSessionManager提供了一系列的构造方法以及HTTP访问的方法。

    @interface AFHTTPSessionManager ()
    @property (readwrite, nonatomic, strong) NSURL *baseURL;
    @end
    
    @implementation AFHTTPSessionManager
    @dynamic responseSerializer;
    
    //类方法,返回一个新创建的AFHTTPSessionManager对象
    + (instancetype)manager {
        return [[[self class] alloc] initWithBaseURL:nil];
    }
    
    //构造函数
    - (instancetype)init {
        return [self initWithBaseURL:nil];
    }
    
    //构造函数
    - (instancetype)initWithBaseURL:(NSURL *)url {
        return [self initWithBaseURL:url sessionConfiguration:nil];
    }
    
    //构造函数
    - (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
        return [self initWithBaseURL:nil sessionConfiguration:configuration];
    }
    
    //构造函数
    - (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;
    }
    
    #pragma mark -
    
    //setter
    - (void)setRequestSerializer:(AFHTTPRequestSerializer <AFURLRequestSerialization> *)requestSerializer {
        NSParameterAssert(requestSerializer);
    
        _requestSerializer = requestSerializer;
    }
    
    //setter
    - (void)setResponseSerializer:(AFHTTPResponseSerializer <AFURLResponseSerialization> *)responseSerializer {
        NSParameterAssert(responseSerializer);
    
        [super setResponseSerializer:responseSerializer];
    }
    
    @dynamic securityPolicy;
    
    //setter设置安全策略
    - (void)setSecurityPolicy:(AFSecurityPolicy *)securityPolicy {
        if (securityPolicy.SSLPinningMode != AFSSLPinningModeNone && ![self.baseURL.scheme isEqualToString:@"https"]) {
            NSString *pinningMode = @"Unknown Pinning Mode";
            switch (securityPolicy.SSLPinningMode) {
                case AFSSLPinningModeNone:        pinningMode = @"AFSSLPinningModeNone"; break;
                case AFSSLPinningModeCertificate: pinningMode = @"AFSSLPinningModeCertificate"; break;
                case AFSSLPinningModePublicKey:   pinningMode = @"AFSSLPinningModePublicKey"; break;
            }
            NSString *reason = [NSString stringWithFormat:@"A security policy configured with `%@` can only be applied on a manager with a secure base URL (i.e. https)", pinningMode];
            @throw [NSException exceptionWithName:@"Invalid Security Policy" reason:reason userInfo:nil];
        }
    
        [super setSecurityPolicy:securityPolicy];
    }
    
    

    上面的方法就是一系列构造函数,用于初始化父类对象以及序列化器,设置安全策略等,没有太多复杂的内容。

    //GET请求,调用下面那个方法
    - (NSURLSessionDataTask *)GET:(NSString *)URLString
                       parameters:(id)parameters
                          success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                          failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
    {
    
        return [self GET:URLString parameters:parameters progress:nil success:success failure:failure];
    }
    
    //GET请求
    - (NSURLSessionDataTask *)GET:(NSString *)URLString
                       parameters:(id)parameters
                         progress:(void (^)(NSProgress * _Nonnull))downloadProgress
                          success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
                          failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
    {
        //调用另一个方法构造GET请求
        NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET"
                                                            URLString:URLString
                                                           parameters:parameters
                                                       uploadProgress:nil
                                                     downloadProgress:downloadProgress
                                                              success:success
                                                              failure:failure];
        
        /*
        启动任务
        使用AFHTTPSessionManager创建的任务默认都帮你启动了,所以不需要手动调用resume方法了
        上一篇中讲解的AFURLSessionManager默认没有启动,所以获取任务后要手动启动
        */
        [dataTask resume];
    
        return dataTask;
    }
    //获取HEAD请求
    - (NSURLSessionDataTask *)HEAD:(NSString *)URLString
                        parameters:(id)parameters
                           success:(void (^)(NSURLSessionDataTask *task))success
                           failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
    {
        //同样调用下面的一个方法来获取
        NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"HEAD" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:^(NSURLSessionDataTask *task, __unused id responseObject) {
            if (success) {
                success(task);
            }
        } failure:failure];
        
        //默认启动任务
        [dataTask resume];
    
        return dataTask;
    }
    //获取POST请求
    - (NSURLSessionDataTask *)POST:(NSString *)URLString
                        parameters:(id)parameters
                           success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                           failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
    {
        //调用下面的方法获取
        return [self POST:URLString parameters:parameters progress:nil success:success failure:failure];
    }
    
    //获取POST请求
    - (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
    {
        //同GET HEAD方法一样,调用一个方法获取任务
        NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"POST" URLString:URLString parameters:parameters uploadProgress:uploadProgress downloadProgress:nil success:success failure:failure];
        //默认启动任务
        [dataTask resume];
    
        return dataTask;
    }
    
    //获取POST上传文件请求
    - (NSURLSessionDataTask *)POST:(NSString *)URLString
                        parameters:(nullable id)parameters
         constructingBodyWithBlock:(nullable void (^)(id<AFMultipartFormData> _Nonnull))block
                           success:(nullable void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
                           failure:(nullable void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
    {
        //调用下面的方法来构造上传文件的POST请求
        return [self POST:URLString parameters:parameters constructingBodyWithBlock:block progress:nil success:success failure:failure];
    }
    
    //上传文件POST请求
    - (NSURLSessionDataTask *)POST:(NSString *)URLString
                        parameters:(id)parameters
         constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
                          progress:(nullable void (^)(NSProgress * _Nonnull))uploadProgress
                           success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                           failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
    {
        //构造一个request请求
        NSError *serializationError = nil;
        NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:&serializationError];
        //如果在做序列化时出错在主线程调用failure回调块
        if (serializationError) {
            if (failure) {
                dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
                    failure(nil, serializationError);
                });
            }
    
            return nil;
        }
        //调用父类的方法获取一个上传的任务
        __block NSURLSessionDataTask *task = [self uploadTaskWithStreamedRequest:request progress:uploadProgress completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
            if (error) {
                if (failure) {
                    failure(task, error);
                }
            } else {
                if (success) {
                    success(task, responseObject);
                }
            }
        }];
        //默认启动任务
        [task resume];
    
        return task;
    }
    
    //获取PUT请求
    - (NSURLSessionDataTask *)PUT:(NSString *)URLString
                       parameters:(id)parameters
                          success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                          failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
    {
        //通过一个通用的方法来获取dataTask
        NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PUT" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure];
        //默认启动任务
        [dataTask resume];
    
        return dataTask;
    }
    
    //同上
    - (NSURLSessionDataTask *)PATCH:(NSString *)URLString
                         parameters:(id)parameters
                            success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                            failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
    {
        NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PATCH" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure];
    
        [dataTask resume];
    
        return dataTask;
    }
    
    //同上
    - (NSURLSessionDataTask *)DELETE:(NSString *)URLString
                          parameters:(id)parameters
                             success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                             failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
    {
        NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"DELETE" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure];
    
        [dataTask resume];
    
        return dataTask;
    }
    
    //一个通用的方法来构造NSURLSessionDataTask
    - (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
    {
        //通过请求序列化器构造一个request请求
        //需要传入请求方法GET POST DELETE PUT这样的字符串 以及相关参数
        NSError *serializationError = nil;
        NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
        //如果序列化失败在主线程中执行failure回调块
        if (serializationError) {
            if (failure) {
                dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
                    failure(nil, serializationError);
                });
            }
    
            return nil;
        }
        
        //序列化成功,调用父类的方法获取dataTask
        __block NSURLSessionDataTask *dataTask = nil;
        dataTask = [self dataTaskWithRequest:request
                              uploadProgress:uploadProgress
                            downloadProgress:downloadProgress
                           completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
            if (error) {
                if (failure) {
                    failure(dataTask, error);
                }
            } else {
                if (success) {
                    success(dataTask, responseObject);
                }
            }
        }];
        //返回dataTask
        return dataTask;
    }
    

    上面的代码也很简单,是在AFURLSessionManager之上做了一些处理,其中涉及的AFURLRequestSerializationAFURLResponseSerialization由于不是本系列文章的关注点所以没有相关讲解,有需要的读者请自行查阅。

    AFHTTPSessionManager继承自AFURLSessionManager并提供了更加便捷的网络请求接口,如果阅读了前一篇AFURLSessionManager可以发现它才是重点。AFHTTPSessionManager只是在它的基础上做了一些简单的封装,提供了更加便捷的接口。

    通过AFURLSessionManagerAFHTTPSessionManager源码的阅读可以学习到AFNetworking在代码设计方面的优点,以及对NSURLSession的使用更清晰了。

    备注

    由于作者水平有限,难免出现纰漏,如有问题还请不吝赐教。

    相关文章

      网友评论

        本文标题:iOS网络——AFNetworking AFHttpSessio

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