AFNetworking 3.x 详解一

2017-07-05  本文已影响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

上一篇下一篇

猜你喜欢

热点阅读