这个类主要实现了对于不同情况的请求的request对象的封装。尤其是对于multipart/form-data类型的request的封装,简化了我们自己封装过程的痛苦。如果我们要使用multipart/form-data类型的请求
字符串编码
将参数进行百分号编码(URL编码)为什么需要Url编码
AFQueryStringPairsFromDictionary(NSDictionary *dictionary);
期间调用全局函数百分号编码
AFPercentEscapedStringFromString(NSString *string)
AFURLRequestSerialization协议
内部使用方法,实现可以在AFJSONRequestSerializer、AFHTTPRequestSerializer、AFPropertyListRequestSerializer情况下对requst的设置恰当的请求头和请求体。
setter方法
AFHTTPRequestSerializerObservedKeyPaths全局方法指定了request请求序列化要观察的属性列表、是一个数组,里面有对蜂窝数据、缓存策略、cookie、管道、网络状态、超时这几个元素。
@property (nonatomic, assign) BOOL allowsCellularAccess;
@property (nonatomic, assign) NSURLRequestCachePolicy cachePolicy;
@property (nonatomic, assign) BOOL HTTPShouldHandleCookies;
@property (nonatomic, assign) BOOL HTTPShouldUsePipelining;
property (nonatomic, assign) NSTimeInterval timeoutInterval;
@property (nonatomic, assign) NSURLRequestNetworkServiceType networkServiceType;
KVO的应用详解键值观察(KVO)及其实现机理
static NSArray * AFHTTPRequestSerializerObservedKeyPaths() {
static NSArray *_AFHTTPRequestSerializerObservedKeyPaths = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_AFHTTPRequestSerializerObservedKeyPaths = @[NSStringFromSelector(@selector(allowsCellularAccess)), NSStringFromSelector(@selector(cachePolicy)), NSStringFromSelector(@selector(HTTPShouldHandleCookies)), NSStringFromSelector(@selector(HTTPShouldUsePipelining)), NSStringFromSelector(@selector(networkServiceType)), NSStringFromSelector(@selector(timeoutInterval))];
});
return _AFHTTPRequestSerializerObservedKeyPaths;
}
//
- (instancetype)init {
self = [super init];
if (!self) {
return nil;
}
…………
self.mutableObservedChangedKeyPaths = [NSMutableSet set];
for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
if ([self respondsToSelector:NSSelectorFromString(keyPath)]) {
[self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:AFHTTPRequestSerializerObserverContext];
}
}
}
NSKeyValueObserving 代理实现
首先通过automaticallyNotifiesObserversForKey方法来阻止一些属性的KVO机制的触发,然后我们通过重写蜂窝数据、缓存策略、cookie、管道、网络状态、超时的观察。可以用于测试这些属性变化是否崩溃等。
- (void)setAllowsCellularAccess:(BOOL)allowsCellularAccess {
[self willChangeValueForKey:NSStringFromSelector(@selector(allowsCellularAccess))];
_allowsCellularAccess = allowsCellularAccess;
[self didChangeValueForKey:NSStringFromSelector(@selector(allowsCellularAccess))];
}
/**
如果kvo的触发机制是默认出发。则返回true,否则返回false。在这里,只要是`AFHTTPRequestSerializerObservedKeyPaths`里面的属性,我们都取消自动出发kvo机制,使用手动触发。
@param key kvo的key
@return bool值
*/
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
if ([AFHTTPRequestSerializerObservedKeyPaths() containsObject:key]) {
return NO;
}
return [super automaticallyNotifiesObserversForKey:key];
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(__unused id)object
change:(NSDictionary *)change
context:(void *)context
{
//是否是选择要观察的属性
if (context == AFHTTPRequestSerializerObserverContext) {
//如果属性值为null,则表示么有这个属性,移除对其的观察
if ([change[NSKeyValueChangeNewKey] isEqual:[NSNull null]]) {
[self.mutableObservedChangedKeyPaths removeObject:keyPath];
} else {
//添加到要观察的属性的集合
[self.mutableObservedChangedKeyPaths addObject:keyPath];
}
}
}
请求头处理
@property (readonly, nonatomic, strong) NSDictionary <NSString *, NSString *> *HTTPRequestHeaders;
//设置一个请求头域
- (void)setValue:(nullable NSString *)value
forHTTPHeaderField:(NSString *)field;
- (nullable NSString *)valueForHTTPHeaderField:(NSString *)field;
//设置Basic Authorization的用户名和密码。记住需要是base64编码格式的
- (void)setAuthorizationHeaderFieldWithUsername:(NSString *)username
password:(NSString *)password;
- (void)clearAuthorizationHeader;
http body设置
//默认直接从参数创建
- (void)setQueryStringSerializationWithStyle:(AFHTTPRequestQueryStringSerializationStyle)style;
//自定义创建body
- (void)setQueryStringSerializationWithBlock:(nullable NSString * (^)(NSURLRequest *request, id parameters, NSError * __autoreleasing *error))block;
创建request对象
/**
根据给定的url、方法名、参数构建一个request。
*/
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
URLString:(NSString *)URLString
parameters:(id)parameters
error:(NSError *__autoreleasing *)error
/**
构建一个multipartForm的request。并且通过`AFMultipartFormData`类型的formData来构建请求体
*/
- (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method
URLString:(NSString *)URLString
parameters:(NSDictionary *)parameters
constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
error:(NSError *__autoreleasing *)error
/**
通过一个Multipart-Form的request创建一个request。新request的httpBody是`fileURL`指定的文件。
并且是通过`HTTPBodyStream`这个属性添加,`HTTPBodyStream`属性的数据会自动添加为httpBody。
*/
- (NSMutableURLRequest *)requestWithMultipartFormRequest:(NSURLRequest *)request
writingStreamContentsToFile:(NSURL *)fileURL
completionHandler:(void (^)(NSError *error))handler
子类
- AFStreamingMultipartFormData
AFStreamingMultipartFormData负责multipart/form-data的Body的具体构建,实现了AFMultipartFormData的代理方法
- AFJSONRequestSerializer
对于AFJSONRequestSerializer。重写了构建request的方法,把Content-Type指定为"application/json"
- AFPropertyListRequestSerializer
AFPropertyListRequestSerializer,也是同样的道理,把Content-Type指定为"application/x-plist"