博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AFNetworking详解(1)
阅读量:6822 次
发布时间:2019-06-26

本文共 10235 字,大约阅读时间需要 34 分钟。

AFNetworking 是一个 iOS 平台的网络框架,简洁易懂,所以在实际项目开发中用的极多,AFNetworking 本质上还是基于苹果自身的网络通信机制,这里就剖析一下其内部代码。

框架概述

将 AFNetworking 代码下载过来,目录树如下:

total 240drwxr-xr-x@ 15 chasontang  staff   510B  4  1 01:28 AFNetworking-rw-r--r--@  1 chasontang  staff   2.5K  4  1 01:28 AFNetworking.podspecdrwxr-xr-x@  5 chasontang  staff   170B  4 27 17:03 AFNetworking.xcodeprojdrwxr-xr-x   4 chasontang  staff   136B  4 27 17:03 AFNetworking.xcworkspace-rw-r--r--@  1 chasontang  staff    87K  4  1 01:28 CHANGELOG.md-rw-r--r--@  1 chasontang  staff   4.1K  4  1 01:28 CONTRIBUTING.mddrwxr-xr-x@ 19 chasontang  staff   646B  4 27 17:04 Exampledrwxr-xr-x@  5 chasontang  staff   170B  4  1 01:28 Framework-rw-r--r--@  1 chasontang  staff   1.1K  4  1 01:28 LICENSE-rw-r--r--@  1 chasontang  staff    14K  4  1 01:28 README.mddrwxr-xr-x@  7 chasontang  staff   238B  4 27 17:10 Testsdrwxr-xr-x@ 22 chasontang  staff   748B  4  1 01:28 UIKit+AFNetworkingdrwxr-xr-x@ 17 chasontang  staff   578B  4  1 01:28 fastlane

但是本质上只有 AFNetworking 文件夹是实际的代码,而其他都是样例工程、测试用例、使用工具类等。AFNetworking 文件夹下只有 6 个类文件和 1 个汇总头文件,总共大约 5000 行代码。

AFNetworking.h - header fileAFNetworkReachabilityManager - classAFSecurityPolicy - classAFURLRequestSerialization - classAFURLResponseSerialization - classAFURLSessionManager - classAFHTTPSessionManager - class

不过需要注意的是,看起来只存 6 个类文件,但是实际上一个类文件中包含了多个存在继承关系的类,这点确实是瑕疵,容易造成误解。

苹果自身提供的网络通信框架也被称之为 URL loading system,主要使用 NSURLSessionNSURLConnection 两个类作为通信管理类,其中,NSURLSession 只能进行异步通信,而且可以进行后台网络通信,只能用于 iOS 7 及以后版本。而 NSURLConnection 既可以异步也可以同步通信。AFNetworking 则是基于这套机制封装的,并且是继承 NSURLSession 类。
注意:本文所指 AFNetworking 是指 3.x 版本,NSURLConnectionOperation 支持已经被移除了,框架要求最低为 iOS 7 版本。
框架类继承如下:

  • NSURLSession

    • AFURLSessionManager

    • AFHTTPSessionManager

  • AFURLRequestSerialization

    • AFHTTPRequestSerializer

    • AFJSONRequestSerializer

    • AFPropertyListRequestSerializer

  • AFURLResponseSerialization

    • AFHTTPResponseSerializer

    • AFJSONResponseSerializer

    • AFXMLParserResponseSerializer

    • AFPropertyListResponseSerializer

    • AFImageResponseSerializer

    • AFCompoundResponseSerializer

  • AFSecurityPolicy

  • AFNetworkReachabilityManager

源代码剖析

AFNetworking.h

#import 
#import
#import
#ifndef _AFNETWORKING_ #define _AFNETWORKING_ #import "AFURLRequestSerialization.h" #import "AFURLResponseSerialization.h" #import "AFSecurityPolicy.h"#if !TARGET_OS_WATCH #import "AFNetworkReachabilityManager.h"#endif #import "AFURLSessionManager.h" #import "AFHTTPSessionManager.h"#endif /* _AFNETWORKING_ */

很常规的思路,导入所需头文件,宏定义用于防止头文件重复包含,苹果手表平台不导入 AFNetworkReachabilityManager 头文件。

AFHTTPSessionManager

首先这个类是继承自 AFURLSessionManager,实现了 <NSSecureCoding, NSCopying> 协议,而 AFURLSessionManager 则是继承自 NSObject,并且实现了 <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate, NSSecureCoding, NSCopying>

对于大多数开发来说,都是使用 AFHTTPSessionManager 作为网络请求中心。其中有两个重要成员变量:requestSerializer、responseSerializer 分别是请求序列化器和回应序列化器,应该不用多说,从字面上也能猜出其内容。然后就分别是以下方法:

+ (instancetype)manager;- (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;- (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;- (nullable NSURLSessionDataTask *)HEAD:(NSString *)URLString                    parameters:(nullable id)parameters                       success:(nullable void (^)(NSURLSessionDataTask *task))success                       failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;- (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;- (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;- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString                    parameters:(nullable id)parameters     constructingBodyWithBlock:(nullable void (^)(id 
formData))block success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure DEPRECATED_ATTRIBUTE;- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(nullable id)parameters constructingBodyWithBlock:(nullable void (^)(id
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;- (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;- (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;- (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;

一个工厂方法,然后就是 GET、HEAD、POST、PUT、PATCH 和 DELETE 方法。标记为 DEPRECATED_ATTRIBUTE 的则是弃用方法,一些方法带有 progressBlock,便于计算加载过程。工厂方法 + (instancetype)manager 实际上还是创建了一个 baseURL 为 nil 的实例,所以应当避免调用工厂方法,而是手动创建对象。而所有初始化方法都会调用 initWithBaseURL:sessionConfiguration: 方法,以下是初始化方法代码:

self = [super initWithSessionConfiguration:configuration];if (!self) {    return nil;}// Ensure terminal slash for baseURL path, so that NSURL +URLWithString:relativeToURL: works as expectedif ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) {    url = [url URLByAppendingPathComponent:@""];}self.baseURL = url;self.requestSerializer = [AFHTTPRequestSerializer serializer];self.responseSerializer = [AFJSONResponseSerializer serializer];return self;

主要就是整理了 baseURL,然后创建了 AFHTTPRequestSerializer 作为请求序列化器,AFJSONResponseSerializer 作为相应序列化器,也就是默认情况下返回 JSON。

再来看请求方法,很容易就能看出其流程为:变体请求方法 -> 基请求方法 -> dataTaskWithHTTPMethod:URLString:parameters:uploadProgress:downloadProgress:success:failure:,就是返回了类型为 NSURLSessionDataTask 的对象,然后调用 [dataTask resume] 执行请求。

- (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) {#pragma clang diagnostic push#pragma clang diagnostic ignored "-Wgnu"            dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{                failure(nil, serializationError);            });#pragma clang diagnostic pop        }        return nil;    }    __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);            }        }    }];    return dataTask;}

注意,除了一个 POST 方法的变体方法以外,这是所有 HTTP 请求方法的公共出口,主要就是创建一个 NSURLSessionDataTask 对象。POST 方法有一个变体方法是使用 FORMDATA 的形式发起 HTTP 请求,所以无法归纳到公共抽象代码内,因此独立实现了其方法,但是实际上也是差不多的,这里就不多讲了。

首先就是创建 NSMutableURLRequest 对象,如果出错,则使用 GCD 调用 failure 回调函数。否则其调用父类的 dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler: 方法创建 NSURLSessionDataTask 对象。

AFNetworkReachabilityManager

这个类用于检查网络联网状态,实际上是模仿苹果官方示例代码 reachability,这里就不提了,各位自行观看代码实现。

转载地址:http://nwgzl.baihongyu.com/

你可能感兴趣的文章
httpclient的几种请求URL的方式
查看>>
UIImageView动画 UISlider控制速度
查看>>
JAVA自学笔记08
查看>>
C/C++——strcpy函数的实现
查看>>
KMP算法
查看>>
leetcode------Symmetric Tree
查看>>
spring声明式事务 同一类内方法调用事务失效
查看>>
C# 利用ICSharpCode.SharpZipLib实现在线加密压缩和解密解压缩
查看>>
zookeeper项目使用几点小结
查看>>
杂物论第一 中华文明的根基
查看>>
c#中 枚举类型的使用(转)
查看>>
linux应用之tomcat的安装及配置(centos)
查看>>
bytes与str
查看>>
转:Socket原理与编程基础
查看>>
linux C 刚初始化后的一个变量在调用一个静态库中函数后被异常修改为乱码
查看>>
记录DHT网络主要功能步骤
查看>>
VS2010使用Qt库
查看>>
Python特殊语法--filter、map、reduce、lambda
查看>>
[原] Jenkins Android 自动打包配置(转)
查看>>
[Redux] Passing the Store Down with <Provider> from React Redux
查看>>