這個(gè)類主要實(shí)現(xiàn)了對(duì)于不同情況的請(qǐng)求的request對(duì)象的封裝。尤其是對(duì)于multipart/form-data類型的request的封裝,簡(jiǎn)化了我們自己封裝過程的痛苦。如果我們要使用multipart/form-data類型的請(qǐng)求
字符串編碼
將參數(shù)進(jìn)行百分號(hào)編碼(URL編碼)為什么需要Url編碼
AFQueryStringPairsFromDictionary(NSDictionary *dictionary);
期間調(diào)用全局函數(shù)百分號(hào)編碼
AFPercentEscapedStringFromString(NSString *string)
AFURLRequestSerialization協(xié)議
內(nèi)部使用方法,實(shí)現(xiàn)可以在AFJSONRequestSerializer、AFHTTPRequestSerializer、AFPropertyListRequestSerializer情況下對(duì)requst的設(shè)置恰當(dāng)?shù)恼?qǐng)求頭和請(qǐng)求體。
setter方法
AFHTTPRequestSerializerObservedKeyPaths全局方法指定了request請(qǐng)求序列化要觀察的屬性列表、是一個(gè)數(shù)組,里面有對(duì)蜂窩數(shù)據(jù)、緩存策略、cookie、管道、網(wǎng)絡(luò)狀態(tài)、超時(shí)這幾個(gè)元素。
@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的應(yīng)用詳解鍵值觀察(KVO)及其實(shí)現(xiàn)機(jī)理
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 代理實(shí)現(xiàn)
首先通過automaticallyNotifiesObserversForKey方法來阻止一些屬性的KVO機(jī)制的觸發(fā),然后我們通過重寫蜂窩數(shù)據(jù)、緩存策略、cookie、管道、網(wǎng)絡(luò)狀態(tài)、超時(shí)的觀察??梢杂糜跍y(cè)試這些屬性變化是否崩潰等。
- (void)setAllowsCellularAccess:(BOOL)allowsCellularAccess {
[self willChangeValueForKey:NSStringFromSelector(@selector(allowsCellularAccess))];
_allowsCellularAccess = allowsCellularAccess;
[self didChangeValueForKey:NSStringFromSelector(@selector(allowsCellularAccess))];
}
/**
如果kvo的觸發(fā)機(jī)制是默認(rèn)出發(fā)。則返回true,否則返回false。在這里,只要是`AFHTTPRequestSerializerObservedKeyPaths`里面的屬性,我們都取消自動(dòng)出發(fā)kvo機(jī)制,使用手動(dòng)觸發(fā)。
@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,則表示么有這個(gè)屬性,移除對(duì)其的觀察
if ([change[NSKeyValueChangeNewKey] isEqual:[NSNull null]]) {
[self.mutableObservedChangedKeyPaths removeObject:keyPath];
} else {
//添加到要觀察的屬性的集合
[self.mutableObservedChangedKeyPaths addObject:keyPath];
}
}
}
請(qǐng)求頭處理
@property (readonly, nonatomic, strong) NSDictionary <NSString *, NSString *> *HTTPRequestHeaders;
//設(shè)置一個(gè)請(qǐng)求頭域
- (void)setValue:(nullable NSString *)value
forHTTPHeaderField:(NSString *)field;
- (nullable NSString *)valueForHTTPHeaderField:(NSString *)field;
//設(shè)置Basic Authorization的用戶名和密碼。記住需要是base64編碼格式的
- (void)setAuthorizationHeaderFieldWithUsername:(NSString *)username
password:(NSString *)password;
- (void)clearAuthorizationHeader;
http body設(shè)置
//默認(rèn)直接從參數(shù)創(chuàng)建
- (void)setQueryStringSerializationWithStyle:(AFHTTPRequestQueryStringSerializationStyle)style;
//自定義創(chuàng)建body
- (void)setQueryStringSerializationWithBlock:(nullable NSString * (^)(NSURLRequest *request, id parameters, NSError * __autoreleasing *error))block;
創(chuàng)建request對(duì)象
/**
根據(jù)給定的url、方法名、參數(shù)構(gòu)建一個(gè)request。
*/
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
URLString:(NSString *)URLString
parameters:(id)parameters
error:(NSError *__autoreleasing *)error
/**
構(gòu)建一個(gè)multipartForm的request。并且通過`AFMultipartFormData`類型的formData來構(gòu)建請(qǐng)求體
*/
- (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method
URLString:(NSString *)URLString
parameters:(NSDictionary *)parameters
constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
error:(NSError *__autoreleasing *)error
/**
通過一個(gè)Multipart-Form的request創(chuàng)建一個(gè)request。新request的httpBody是`fileURL`指定的文件。
并且是通過`HTTPBodyStream`這個(gè)屬性添加,`HTTPBodyStream`屬性的數(shù)據(jù)會(huì)自動(dòng)添加為httpBody。
*/
- (NSMutableURLRequest *)requestWithMultipartFormRequest:(NSURLRequest *)request
writingStreamContentsToFile:(NSURL *)fileURL
completionHandler:(void (^)(NSError *error))handler
子類
- AFStreamingMultipartFormData
AFStreamingMultipartFormData負(fù)責(zé)multipart/form-data的Body的具體構(gòu)建,實(shí)現(xiàn)了AFMultipartFormData的代理方法
- AFJSONRequestSerializer
對(duì)于AFJSONRequestSerializer。重寫了構(gòu)建request的方法,把Content-Type指定為"application/json"
- AFPropertyListRequestSerializer
AFPropertyListRequestSerializer,也是同樣的道理,把Content-Type指定為"application/x-plist"