美文网首页
AFNetworking 3.x 详解一

AFNetworking 3.x 详解一

作者: 纯情_小火鸡 | 来源:发表于2017-07-05 16:49 被阅读429次

    首先我们来分析一下** AFHTTPSessionManager AFHTTPRequestSerializer **

    AFHTTPSessionManager

    AFHTTPSessionManager 继承自AFURLSessionManager,虽然提供了许多对外的请求方法,但是他本身没做什么事情,都是调用了父类的方法以及AFHTTPRequestSerializer请求序列化的方法,比如发送一个GET请求对应会调用到dataTaskWithHTTPMethod方法中,首先请求序列化,失败则提示,成功则调用父类的dataTaskWithRequest方法发起请求。

    
    - (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
                                           URLString:(NSString *)URLString
                                          parameters:(id)parameters
                                      uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress
                                    downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress
                                             success:(void (^)(NSURLSessionDataTask *, id))success
                                             failure:(void (^)(NSURLSessionDataTask *, NSError *))failure
    {
        NSError *serializationError = nil;
        NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
        if (serializationError) {
            if (failure) {
                dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
                    failure(nil, serializationError);
                });
            }
    
            return nil;
        }
    
        __block NSURLSessionDataTask *dataTask = nil;
        dataTask = [self dataTaskWithRequest:request
                              uploadProgress:uploadProgress
                            downloadProgress:downloadProgress
                           completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
            if (error) {
                if (failure) {
                    failure(dataTask, error);
                }
            } else {
                if (success) {
                    success(dataTask, responseObject);
                }
            }
        }];
    
        return dataTask;
    }
    

    AFHTTPRequestSerializer

    接下来我们看下AFHTTPRequestSerializer这个类是如何进行请求序列化的

    - (NSMutableURLRequest *)requestWithMethod:(NSString *)method
                                     URLString:(NSString *)URLString
                                    parameters:(id)parameters
                                         error:(NSError *__autoreleasing *)error
    {
        NSParameterAssert(method);
        NSParameterAssert(URLString);
    
        NSURL *url = [NSURL URLWithString:URLString];
    
        NSParameterAssert(url);
    
        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];
            }
        }
    
        mutableRequest = [[self requestBySerializingRequest:mutableRequest withParameters:parameters error:error] mutableCopy];
    
        return mutableRequest;
    }
    

    这个方法用于使用指定的HTTP方法和URL字符串创建一个** nsmutableurlrequest 对象。
    如果
    HTTP方法是GET, HEAD, DELETE,则这些参数将用于构造一个URL编码的查询字符串,该字符串被追加到请求的URL中,参数将放在url中以key=value的方式编码。否则,将根据** parameterencoding **属性的值进行编码,并设置为请求体。

    - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
                                   withParameters:(id)parameters
                                            error:(NSError *__autoreleasing *)error
    {
        NSParameterAssert(request);
    
        NSMutableURLRequest *mutableRequest = [request mutableCopy];
    
        [self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
            if (![request valueForHTTPHeaderField:field]) {
                [mutableRequest setValue:value forHTTPHeaderField:field];
            }
        }];
    
        NSString *query = nil;
        if (parameters) {
            if (self.queryStringSerialization) {
                NSError *serializationError;
                query = self.queryStringSerialization(request, parameters, &serializationError);
    
                if (serializationError) {
                    if (error) {
                        *error = serializationError;
                    }
    
                    return nil;
                }
            } else {
                switch (self.queryStringSerializationStyle) {
                    case AFHTTPRequestQueryStringDefaultStyle:
                        query = AFQueryStringFromParameters(parameters);
                        break;
                }
            }
        }
    
        if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {
            if (query && query.length > 0) {
                mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? @"&%@" : @"?%@", query]];
            }
        } else {
            // #2864: an empty string is a valid x-www-form-urlencoded payload
            if (!query) {
                query = @"";
            }
            if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {
                [mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
            }
            [mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]];
        }
    
        return mutableRequest;
    }
    

    该方法使用原始请求的副本编码并返回一个带有指定参数的请求。首先会遍历** HTTPRequestHeaders 为请求设置请求头,然后根据条件设置查询参数,最后根据请求方法将 parameters **拼接到URL或者 添加到HTTP body中。

    - (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method
                                                  URLString:(NSString *)URLString
                                                 parameters:(NSDictionary *)parameters
                                  constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
                                                      error:(NSError *__autoreleasing *)error
    {
        NSParameterAssert(method);
        NSParameterAssert(![method isEqualToString:@"GET"] && ![method isEqualToString:@"HEAD"]);
    
        NSMutableURLRequest *mutableRequest = [self requestWithMethod:method URLString:URLString parameters:nil error:error];
    
        __block AFStreamingMultipartFormData *formData = [[AFStreamingMultipartFormData alloc] initWithURLRequest:mutableRequest stringEncoding:NSUTF8StringEncoding];
    
        if (parameters) {
            for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) {
                NSData *data = nil;
                if ([pair.value isKindOfClass:[NSData class]]) {
                    data = pair.value;
                } else if ([pair.value isEqual:[NSNull null]]) {
                    data = [NSData data];
                } else {
                    data = [[pair.value description] dataUsingEncoding:self.stringEncoding];
                }
    
                if (data) {
                    [formData appendPartWithFormData:data name:[pair.field description]];
                }
            }
        }
    
        if (block) {
            block(formData);
        }
    
        return [formData requestByFinalizingMultipartFormData];
    }
    

    该方法使用指定的** HTTP **方法 和 ** URLString 创建一个 NSMutableURLRequest对象,并使用指定的参数和多部分数据块构建了一个multipart/form-data HTTP **体。详解:首先判断请求方法是否不是 HEADGET,然后根据定的HTTP方法和URL字符串创建一个NSMutableURLRequest对象,,然后创建一个AFStreamingMultipartFormData对象,http最终上传的数据包括参数,以及要上传的文件数据都放这里。(AFStreamingMultipartFormData对象包含AFMultipartBodyStream *bodyStream属性,是实现了NSInputStream的子类,[self.currentHTTPBodyPart read:&buffer[totalNumberOfBytesRead]会将数据写入缓冲区)如果参数存在,则key-value转换成NSData封装成一个AFHTTPBodyPart对象放入HTTPBodyParts中,并重新设置初始和最终边界,以确保Content-Length正确,然后返回 NSMutableURLRequest对象。

    而对于** AFJSONRequestSerializer AFPropertyListRequestSerializer **,无非都是继承自AFHTTPRequestSerializer,在
    <pre>- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
    withParameters:(id)parameters
    error:(NSError *__autoreleasing *)error
    </pre>方法中修改Content-Typeapplication/json或是application/x-plist

    相关文章

      网友评论

          本文标题:AFNetworking 3.x 详解一

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