AFN - AFURLRequestSerialization

这个类主要实现了对于不同情况的请求的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  *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  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"

你可能感兴趣的:(AFN - AFURLRequestSerialization)