AFNetworking3详解

本文深入讲解了AFNetworking的模块划分及工作原理,重点介绍了Serialization模块的功能与实现细节,包括AFURLRequestSerialization和AFURLResponseSerialization的作用,以及AFHTTPRequestSerializer类的属性和API。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

AFNetworking是iOS开发中最常用的第三方开源库之一,它主要用于进行网络请求。AFNetworking主要是对HTTP协议和iOS网络相关库的封装,读一读源码可以加深对HTTP协议和iOS网络编程的理解。

AFNetworking的结构

AFNetworking主要分为四个模块:

  • 处理请求和回复的序列化模块:Serialization
  • 网络安全模块:Security
  • 网络监测模块:Reachability
  • 处理通讯的会话模块:NSURLSession
    其中NSURLSession是最常使用的模块,也是综合模块,它引用了其他的几个模块,而其他几个模块都是独立的模块,所以对AFNetworking的学习就先从这些单独的模块开始。

Serialization模块

Serialization模块包括请求序列化AFURLRequestSerialization和响应序列化AFURLResponseSerialization,它们主要功能:

  • AFURLRequestSerialization用来将字典参数编码成URL传输参数,并提供上传文件的基本功能实现。
  • AFURLResponseSerialization用来处理服务器返回数据,提供返回码校验和数据校验的功能。

Serialization分为四个文件,分别来看这四个文件的内容。

AFURLRequestSerialization.h

先声明了一个协议AFURLRequestSerialization继承了NSSecureCodingNSCopying来保证所有实现这个序列化协议的序列化器类都有安全编码复制的能力。协议也定义了序列化的规范方法。(虽然目前只有一个类实现了协议,感觉没啥必要..但这是一种规范,有利于扩展。)

/**
    AFURLRequestSerialization协议可以被一个编码特定http请求的对象实现。
    请求序列化器(Request serializer)可以编码查询语句、HTTP请求体,如果必须的话,可以自行设置合适的HTTP请求体内容(如:Agent:iOS)。
    例如,一个JSON请求序列化器会把请求体Content-Type设置为application/json。
*/
@protocol AFURLRequestSerialization <NSObject, NSSecureCoding, NSCopying>

/**
    返回一个使用了指定参数编码的请求的拷贝。
*/
- (nullable NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
                               withParameters:(nullable id)parameters
                                        error:(NSError * _Nullable __autoreleasing *)error NS_SWIFT_NOTHROW;
@end

公开属性

HTTP序列化器类AFHTTPRequestSerializer,实现了AFURLRequestSerialization协议,并参考了NSMutableURLRequest类声明了很多请求设置相关属性。

AFHTTPRequestSerializer和其主要公开属性

/**
    AFHTTPRequestSerializer实现了AFURLRequestSerialization协议,为查询语句、URL表单编码参数的序列化提供一个具体的实现和默认的请求头,以及状态码和内容类型的校验。
    所有的request和response都被鼓励去继承AFHTTPRequestSerializer类,以确保默认方法和属性的一致性。
*/
@interface AFHTTPRequestSerializer : NSObject <AFURLRequestSerialization>

/**
    字符串编码方式,默认为NSUTF8StringEncoding
*/
@property (nonatomic, assign) NSStringEncoding stringEncoding;
/**
    缓存策略。默认为NSURLRequestUseProtocolCachePolicy
    参考NSMutableURLRequest -setCachePolicy:
*/
@property (nonatomic, assign) NSURLRequestCachePolicy cachePolicy;
/**
    是否用cookie来处理创建的请求。默认为YES
    参考NSMutableURLRequest -setHTTPShouldHandleCookies
*/
@property (nonatomic, assign) BOOL HTTPShouldHandleCookies;
/**
    创建的请求在收到上个传输(transmission)响应之前是否继续发送数据。
    默认为NO(即等待上次传输完成后再请求)
    参考NSMutableURLRequest -setHTTPShouldUsePipelining:
*/
@property (nonatomic, assign) BOOL HTTPShouldUsePipelining;
/**
    请求的网络服务类型。
    这个服务类型向整个网络传输层次提供了一个关于该请求目的的提示。
    (The service type is used to provide the networking layers a hint of the purpose of the request.)
    默认为NSURLNetworkServiceTypeDefault
    参考NSMutableURLRequest -setNetworkServiceType:
*/
@property (nonatomic, assign) NSURLRequestNetworkServiceType networkServiceType;
/**
    请求的超时间隔,单位秒。默认为60秒
    参考NSMutableURLRequest -setTimeoutInterval:
*/
@property (nonatomic, assign) NSTimeInterval timeoutInterval;
/**
    序列请求的默认请求头。默认值包括
    'Accept-Language’  内容为 'NSLocale +preferredLanguages’ 方法获取的语音
    'User-Agent’  内容为各种bundle的标志已经系统信息
    可以使用'setValue:forHTTPHeaderField:’方法添加或删除请求头
*/
@property (readonly, nonatomic, strong) NSDictionary <NSString *, NSString *> *HTTPRequestHeaders;

/**
    哪些HTTP请求方法会将参数编码成查询字符串(如:name=xgb&gender=1)。默认为GET, HEAD和DELETE。
*/
@property (nonatomic, strong) NSSet <NSString *> *HTTPMethodsEncodingParametersInURI;

/**
    需要将参数转换成查询语句的HTTP请求方式。默认包括GET、HEAD和DELETE。
*/
@property (nonatomic, strong) NSSet <NSString *> *HTTPMethodsEncodingParametersInURI;

@end

属性的理解:
stringEncoding一般服务器都是utf-8格式,没必要用到其他
cachePolicy缓存策略,苹果主要定义了四种可供选择的缓存策略:

/**
    NSURLRequestUseProtocolCachePolicy是默认的缓存策略,它使用当前URL的协议中预置的缓存策略,无论这个协议是http,还是说你自己定义协议。
    对于常见的http协议来说,这个策略根据请求的头来执行缓存策略。服务器可以在返回的响应头中加入Expires策略或者Cache-Control策略来告诉客户端应该执行的缓存行为,同时配合Last-Modified等头来控制刷新的时机。
    关于详细的web缓存处理https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=zh-cn
*/
NSURLRequestUseProtocolCachePolicy
/**
    不使用缓存,相当于请求头的no-store,在进行包含个人隐私数据或银行业务数据等敏感信息的请求时可以使用。
*/
NSURLRequestReloadIgnoringCacheData
/**
    NSURLRequestReturnCacheDataElseLoad 这个策略比较有趣,它会一直偿试读取缓存数据,直到无法没有缓存数据的时候,才会去请求网络。
    这个策略有一个重大的缺陷导致它根本无法被使用,即它根本没有对缓存的刷新时机进行控制,如果你要去使用它,那么需要额外的进行对缓存过期进行控制。
*/
NSURLRequestReturnCacheDataElseLoad
/**
    只读缓存并且即时缓存不存在都不去请求
*/
NSURLRequestReturnCacheDataDontLoad

HTTPShouldHandleCookiesHTTPShouldUsePipelining这两个属性一般不需要修改,使用默认即可。
networkServiceType用于设置这个请求的系统处理优先级,这个属性会影响系统对网络请求的唤醒速度,例如FaceTime使用了VoIP协议就需要设置为NSURLNetworkServiceTypeVoIP来使得在后台接收到数据时也能快速唤醒应用,一般情况下不需要用到。
timeoutInterval请求超时时间。
HTTPRequestHeaders其他请求头设置。

API

AFHTTPRequestSerializer的API分两种,一种是普通的参数请求,另一种是需要上传文件的请求,如下:

/** 通过URL字符串和字典参数来构建请求 */
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
                                 URLString:(NSString *)URLString
                                parameters:(nullable id)parameters
                                     error:(NSError * _Nullable __autoreleasing *)error;

/** 上传文件的API,需要通过实现了AFMultipartFormData协议的formData对象处理待上传文件 */                     
- (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method
                                              URLString:(NSString *)URLString
                                             parameters:(nullable NSDictionary <NSString *, id> *)parameters
                              constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block
                                                  error:(NSError * _Nullable __autoreleasing *)error;

AFMultipartFormData协议

AFHTTPRequestSerializer实现了对上传文件的支持,AFMultipartFormData协议就是定义添加需上传文件的方法,有类似以下的方法:

/** 通过URL定位待上传文件 */
- (BOOL)appendPartWithFileURL:(NSURL *)fileURL
                         name:(NSString *)name
                        error:(NSError * _Nullable __autoreleasing *)error;
                        
/** 通过NSInputStream定义待上传文件 */
 - (void)appendPartWithInputStream:(nullable NSInputStream *)inputStream
                             name:(NSString *)name
                         fileName:(NSString *)fileName
                           length:(int64_t)length
                         mimeType:(NSString *)mimeType;
                         
/** 通过NSData数据上传 */
- (void)appendPartWithFileData:(NSData *)data
                          name:(NSString *)name
                      fileName:(NSString *)fileName
                      mimeType:(NSString *)mimeType;

AFURLRequestSerialization.m

工具方法

在了解AFURLRequestSerialization怎么实现之前,先来看下AFURLRequestSerialization.m定义的一些工具方法:

  • AFPercentEscapedStringFromString方法用于将字符串转化成符合标准的URL编码字符串,代码如下:
NSString * AFPercentEscapedStringFromString(NSString *string) {
    // does not include "?" or "/" due to RFC 3986 - Section 3.4
    static NSString * const kAFCharactersGeneralDelimitersToEncode = @":#[]@";
    static NSString * const kAFCharactersSubDelimitersToEncode = @"!$&'()*+,;=";

    NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
    [allowedCharacterSet removeCharactersInString:[kAFCharactersGeneralDelimitersToEncode stringByAppendingString:kAFCharactersSubDelimitersToEncode]];

    static NSUInteger const batchSize = 50;

    NSUInteger index = 0;
    NSMutableString *escaped = @"".mutableCopy;

    while (index < string.length) {
        NSUInteger length = MIN(string.length - index, batchSize);
        NSRange range = NSMakeRange(index, length);

        // To avoid breaking up character sequences such as 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值