iOS学习----------AFNetworking(2)request创建和请求参数的序列化
2016-03-02 17:35
519 查看
为了迎合iOS新版本的升级, AFNetworking在3.0版本中删除了基于 NSURLConnection API的所有支持。如果你的项目以前使用过这些API,建议您立即升级到基于 NSURLSession 的API的AFNetworking的版本。迁移方法:AFNetworking 3.0迁移指南
AFNetworking源码大致分为以下几个部分:
网络监控:AFNetworkReachabilityManager
网络安全策略:AFSecurityPolicy
请求数据序列化:AFURLRequestSerialization
响应数据序列化:AFURLResponseSerialization
网络请求管理:AFURLSessionManager(AFHTTPSessionManager继承于AFURLSessionManager)
本部分主要介绍请求数据序列化同时包含request的创建(AFURLRequestSerialization)
AFURLRequestSerialization.h文件
协议:AFURLRequestSerialization
协议方法:
协议:AFMultipartFormData
方法:
类:AFHTTPRequestSerializer、AFPropertyListRequestSerializer
AFURLRequestSerialization.m文件
创建NSMutableURLRequest对象,从第一个方法入手
AFHTTPRequestSerializerObservedKeyPaths()方法,将本类中的key path(就是属性名)搜集在一起
这几种keypath的意思如下:
allowsCellularAccess: 是否允许使用设备的蜂窝移动网络来创建request,默认为允许
cachePolicy: 创建的request所使用的缓存策略,默认使用
HTTPShouldHandleCookies:
如果设置HTTPShouldHandleCookies为YES,就处理存储在NSHTTPCookieStore中的cookies
HTTPShouldHandleCookies表示是否应该给request设置cookie并随request一起发送出去
HTTPShouldUsePipelining:HTTPShouldUsePipelining表示receiver(理解为iOS客户端)的下一个信息是否必须等到上一个请求回复才能发送。
如果为YES表示可以,NO表示必须等receiver收到先前的回复才能发送下个信息。
networkServiceType: 设定request的network service类型. 默认是
这个network service是为了告诉系统网络层这个request使用的目的 比如NSURLNetworkServiceTypeVoIP表示的就这个request是用来请求网际协议通话技术(Voice over IP)。
系统能根据提供的信息来优化网络处理,从而优化电池寿命,网络性能等等
timeoutInterval:超时时间 60秒
第二部分代码--设置request的header field 和序列化参数(get 、head 、delete这三种方法创建request)
AFN内部的序列化方法
根本方法为:
AFNetworking源码大致分为以下几个部分:
网络监控:AFNetworkReachabilityManager
网络安全策略:AFSecurityPolicy
请求数据序列化:AFURLRequestSerialization
响应数据序列化:AFURLResponseSerialization
网络请求管理:AFURLSessionManager(AFHTTPSessionManager继承于AFURLSessionManager)
本部分主要介绍请求数据序列化同时包含request的创建(AFURLRequestSerialization)
AFURLRequestSerialization.h文件
协议:AFURLRequestSerialization
协议方法:
- (nullable NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request withParameters:(nullable id)parameters error:(NSError * _Nullable __autoreleasing *)error NS_SWIFT_NOTHROW;
协议:AFMultipartFormData
方法:
- (BOOL)appendPartWithFileURL:(NSURL *)fileURL name:(NSString *)name error:(NSError * _Nullable __autoreleasing *)error; - (BOOL)appendPartWithFileURL:(NSURL *)fileURL name:(NSString *)name fileName:(NSString *)fileName mimeType:(NSString *)mimeType - (void)appendPartWithInputStream:(nullable NSInputStream *)inputStream name:(NSString *)name fileName:(NSString *)fileName length:(int64_t)length mimeType:(NSString *)mimeType; - (void)appendPartWithFileData:(NSData *)data name:(NSString *)name fileName:(NSString *)fileName mimeType:(NSString *)mimeType; - (void)appendPartWithFormData:(NSData *)data name:(NSString *)name; - (void)appendPartWithHeaders:(nullable NSDictionary <NSString *, NSString *> *)headers body:(NSData *)body; - (void)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes delay:(NSTimeInterval)delay;
类:AFHTTPRequestSerializer、AFPropertyListRequestSerializer
AFURLRequestSerialization.m文件
创建NSMutableURLRequest对象,从第一个方法入手
/** 使用指定的HTTP method和URLString来构建一个NSMutableURLRequest对象实例 如果method是GET、HEAD、DELETE,那parameter将会被用来构建一个基于url编码的查询字符串(query url) ,并且这个字符串会直接加到request的url后面。对于其他的Method,比如POST/PUT,它们会根 据parameterEncoding属性进行编码,而后加到request的http body上。 @param method request的HTTP methodt,比如 `GET`, `POST`, `PUT`, or `DELETE`. 该参数不能为空 @param URLString 用来创建request的URL @param parameters 既可以对method为GET的request设置一个查询字符串(query string),也可以设置到request的HTTP body上 @param error 构建request时发生的错误 @return 一个NSMutableURLRequest的对象 */ - (NSMutableURLRequest *)requestWithMethod:(NSString *)method URLString:(NSString *)URLString parameters:(id)parameters error:(NSError *__autoreleasing *)error { //断言 //方法或函数应当在代码最开始处使用 NSParameterAssert / NSCParameterAssert 来强制输入的值满足先验条件,这是一条金科玉律;其他情况下使用 NSAssert / NSCAssert。 NSParameterAssert(method); NSParameterAssert(URLString); NSURL *url = [NSURL URLWithString:URLString]; NSParameterAssert(url); //创建mutableRequest病指定请求方法 NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url]; mutableRequest.HTTPMethod = method; //通过循环将本类中的几个keypath设置在mutableRequest中 //AFHTTPRequestSerializerObservedKeyPaths()方法为初始化各个key path for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) { if ([self.mutableObservedChangedKeyPaths containsObject:keyPath]) { //使用kvc的方式设置mutableRequest的属性 [mutableRequest setValue:[self valueForKeyPath:keyPath] forKey:keyPath]; } } //设置request的http header field 和序列化参数 mutableRequest = [[self requestBySerializingRequest:mutableRequest withParameters:parameters error:error] mutableCopy]; return mutableRequest; }
AFHTTPRequestSerializerObservedKeyPaths()方法,将本类中的key path(就是属性名)搜集在一起
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; }
这几种keypath的意思如下:
allowsCellularAccess: 是否允许使用设备的蜂窝移动网络来创建request,默认为允许
cachePolicy: 创建的request所使用的缓存策略,默认使用
NSURLRequestUseProtocolCachePolicy,该策略表示,如果缓存不存在,直接从服务端获取。如果缓存存在,会根据response中的Cache-Control字段判断,下一步操作,如: Cache-Control字段为must-revalidata, 则 询问服务端该数据是否有更新,无更新话直接返回给用户缓存数据,若已更新,则请求服务端.
HTTPShouldHandleCookies:
如果设置HTTPShouldHandleCookies为YES,就处理存储在NSHTTPCookieStore中的cookies
HTTPShouldHandleCookies表示是否应该给request设置cookie并随request一起发送出去
HTTPShouldUsePipelining:HTTPShouldUsePipelining表示receiver(理解为iOS客户端)的下一个信息是否必须等到上一个请求回复才能发送。
如果为YES表示可以,NO表示必须等receiver收到先前的回复才能发送下个信息。
networkServiceType: 设定request的network service类型. 默认是
NSURLNetworkServiceTypeDefault.
这个network service是为了告诉系统网络层这个request使用的目的 比如NSURLNetworkServiceTypeVoIP表示的就这个request是用来请求网际协议通话技术(Voice over IP)。
系统能根据提供的信息来优化网络处理,从而优化电池寿命,网络性能等等
timeoutInterval:超时时间 60秒
第二部分代码--设置request的header field 和序列化参数(get 、head 、delete这三种方法创建request)
- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request withParameters:(id)parameters error:(NSError *__autoreleasing *)error { //request不能为空 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) { //自定义序列化的block,如果用户实现了这个方法就调用这个block if (self.queryStringSerialization) { NSError *serializationError; query = self.queryStringSerialization(request, parameters, &serializationError); if (serializationError) { if (error) { *error = serializationError; } return nil; } } else { //使用afn内部的序列化方法 switch (self.queryStringSerializationStyle) { case AFHTTPRequestQueryStringDefaultStyle: query = AFQueryStringFromParameters(parameters); break; } } } //将序列化后的参数与url进行拼接 //HTTPMethodsEncodingParametersInURI:GET, HEAD, DELETE if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) { /*mutableRequest.URL.query ? @"&%@" : @"?%@", query判断后面是否有参数,如果有参数 用&号拼接 如果没有参数使用?拼接 */ if (query) { 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; }
AFN内部的序列化方法
NSString * AFQueryStringFromParameters(NSDictionary *parameters) { NSMutableArray *mutablePairs = [NSMutableArray array]; for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) { [mutablePairs addObject:[pair URLEncodedStringValue]]; } return [mutablePairs componentsJoinedByString:@"&"]; } NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary) { return AFQueryStringPairsFromKeyAndValue(nil, dictionary); }
根本方法为:
序列化请求参数 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) { // 递归解析数据,baz[]=1&baz[]=2&baz[]=3&foo=bar [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; }
相关文章推荐
- hdoj 5496 Beauty of Sequence
- 设置UIImage 圆角
- iOS之UIButton基本用法
- UISearchBar改变输入框的背景颜色
- UISearchBar控件
- 77.In the CUSTOMERS table, the CUST_CITY column contains the value 'Paris' for the
- (Educational Codeforces Round 9)Longest Subsequence(dp)
- android开发我的新浪微博客户端-载入页面UI篇(1.1)
- Ant之build.xml详解
- UE4材质初探(转载)
- UIScrollView控件介绍
- 浏览器Quirksmode与CSS1compat
- 浏览器Quirksmode与CSS1compat
- 浏览器Quirksmode与CSS1compat
- 浏览器Quirksmode与CSS1compat
- 浏览器Quirksmode与CSS1compat
- 浏览器Quirksmode与CSS1compat
- 浏览器Quirksmode与CSS1compat
- 浏览器Quirksmode与CSS1compat
- 浏览器Quirksmode与CSS1compat