美文网首页
AFURLRequestSerialization

AFURLRequestSerialization

作者: Crazy2015 | 来源:发表于2017-07-31 17:37 被阅读14次
    主要分四个功能:
    1. 处理查询的 URL 参数
    2. 设置 HTTP 头部字段
    3. 设置请求的属性
    4. 分块上传

    处理查询参数

    处理查询参数这部分主要是通过 AFQueryStringPair 还有一些 C 函数来完成的,这个类有两个属性 field 和 value 对应 HTTP 请求的查询 URL 中的参数。

    @interface AFQueryStringPair : NSObject
    @property (readwrite, nonatomic, strong) id field;
    @property (readwrite, nonatomic, strong) id value;
    
    - (instancetype)initWithField:(id)field value:(id)value;
    - (NSString *)URLEncodedStringValue;
    @end
    

    其中的 - [AFQueryStringPair URLEncodedStringValue] 方法会返回 key=value 这种格式,同时使用 AFPercentEscapedStringFromString 函数来对 field 和 value 进行处理,将其中的 :#[]@!$&'()*+,;= 等字符转换为百分号表示的形式。
    这一部分代码还负责返回查询参数,将 AFQueryStringPair 或者 key value 转换为以下这种形式:

    username=dravenss&password=123456&hello[world]=helloworld
    

    它的实现主要依赖于一个递归函数 AFQueryStringPairsFromKeyAndValue,如果当前的 value 是一个集合类型的话,那么它就会不断地递归调用自己。

    NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
        NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
    
        NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(compare:)];
    
        if ([value isKindOfClass:[NSDictionary class]]) {
            NSDictionary *dictionary = value;
            // Sort dictionary keys to ensure consistent ordering in query string, which is important when deserializing potentially ambiguous sequences, such as an array of dictionaries
            for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
                id nestedValue = dictionary[nestedKey];
                if (nestedValue) {
                    [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
                }
            }
        } else if ([value isKindOfClass:[NSArray class]]) {
            NSArray *array = value;
            for (id nestedValue in array) {
                [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
            }
        } else if ([value isKindOfClass:[NSSet class]]) {
            NSSet *set = value;
            for (id obj in [set sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
                [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue(key, obj)];
            }
        } else {
            [mutableQueryStringComponents addObject:[[AFQueryStringPair alloc] initWithField:key value:value]];
        }
    
        return mutableQueryStringComponents;
    }
    
    

    最后返回一个数组

    [
        username=draveness,
        password=123456,
        hello[world]=helloworld
    ]
    

    得到这个数组之后就会调用 AFQueryStringFromParameters 使用 & 来拼接它们。

    static NSString * AFQueryStringFromParameters(NSDictionary *parameters) {
        NSMutableArray *mutablePairs = [NSMutableArray array];
        for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) {
            [mutablePairs addObject:[pair URLEncodedStringValue]];
        }
    
        return [mutablePairs componentsJoinedByString:@"&"];
    }
    

    设置 HTTP 头部字段

    AFHTTPRequestSerializer 在头文件中提供了一些属性方便我们设置 HTTP 头部字段。同时,在类的内部,它提供了 - [AFHTTPRequestSerializer setValue:forHTTPHeaderField:] 方法来设置 HTTP 头部,其实它的实现都是基于一个名为 mutableHTTPRequestHeaders 的属性的:

    - (void)setValue:(NSString *)value
    forHTTPHeaderField:(NSString *)field
    {
        [self.mutableHTTPRequestHeaders setValue:value forKey:field];
    }
    
    - (NSString *)valueForHTTPHeaderField:(NSString *)field {
        return [self.mutableHTTPRequestHeaders valueForKey:field];
    }
    

    设置请求的属性

    还有一写 NSURLRequest 的属性是通过另一种方式来设置的,AFNetworking 为这些功能提供了接口

    @property (nonatomic, assign) BOOL allowsCellularAccess;
    
    @property (nonatomic, assign) NSURLRequestCachePolicy cachePolicy;
    
    @property (nonatomic, assign) BOOL HTTPShouldHandleCookies;
    
    @property (nonatomic, assign) BOOL HTTPShouldUsePipelining;
    
    @property (nonatomic, assign) NSURLRequestNetworkServiceType networkServiceType;
    
    @property (nonatomic, assign) NSTimeInterval timeoutInterval;
    
    

    它们都会通过 AFHTTPRequestSerializerObservedKeyPaths 的调用而返回。

    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;
    }
    
    

    在这些属性被设置时,会触发 KVO,然后将新的属性存储在一个名为 mutableObservedChangedKeyPaths 的字典中:

    - (void)observeValueForKeyPath:(NSString *)keyPath
                          ofObject:(__unused id)object
                            change:(NSDictionary *)change
                           context:(void *)context
    {
        if (context == AFHTTPRequestSerializerObserverContext) {
            if ([change[NSKeyValueChangeNewKey] isEqual:[NSNull null]]) {
                [self.mutableObservedChangedKeyPaths removeObject:keyPath];
            } else {
                [self.mutableObservedChangedKeyPaths addObject:keyPath];
            }
        }
    }
    

    然后会在生成 NSURLRequest 的时候设置这些属性。

    NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url];
    mutableRequest.HTTPMethod = method;
    
    for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
        if ([self.mutableObservedChangedKeyPaths containsObject:keyPath]) {
            [mutableRequest setValue:[self valueForKeyPath:keyPath] forKey:keyPath];
        }
    }
    

    http://draveness.me/afnetworking3.html
    z

    相关文章

      网友评论

          本文标题:AFURLRequestSerialization

          本文链接:https://www.haomeiwen.com/subject/guphlxtx.html