源码:https://github.com/AFNetworking/AFNetworking
关于AFNetworking的请求响应数据序列化
- requestSerializer 是 AFNetworking 请求参数编码的序列化器,它一共有三种编码格式:(默认二进制的数据格式)
AFHTTPRequestSerializer:(默认)第一种是普通的http的编码格式
也就是这种格式 mid=10&method=userInfo&dateInt=20160818
AFJSONRequestSerializer:第二种也是json编码格式的
也就是这种格式 {"mid":"11","method":"userInfo","dateInt":"20160818"}
AFPropertyListRequestSerializer:第三种编码成pislt格式的参数
注意: AFHTTPRequestSerializer,也就是二进制格式是AFNetworking的默认请求编码格式,因此我们的参数如果是json编码格式,就需要修改请求头的编码格式
一般我们的请求设置过程如下
//实例化AFHTTPSessionManager
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//通过requestSerializer修改请求的编码格式(默认二进制格式)
manager.requestSerializer = [AFJSONRequestSerializer serializer];
responseSerializer 是 AFNetworking 响应编码的序列化器,它一共有三种编码格式:(默认直接解析JSON)
self.responseSerializer = [AFJSONResponseSerializer serializer];
AFHTTPResponseSerializer HTTP
AFJSONResponseSerializer JSON (默认)
AFXMLParserResponseSerializer XML的解析器(只能返回XMLParser,还需要自己通过代理方法解析 )
AFImageResponseSerializer Image (AFN同样提供了异步加载网络图片的功能 但是:不支持 GIF,只有 SDWebImage 支持)
AFCompoundResponseSerializer 组合
AFXMLDocumentResponseSerializer (Mac OS X)
AFPropertyListResponseSerializer PList
通过下面的代码设置响应解析器:
//实例化AFHTTPSessionManager
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//通过responseSerializer修改响应的编码格式(默认就是JSON格式)
manager.responseSerializer = [AFJSONResponseSerializer serializer];
acceptableContentTypes 响应可接受类型
AFNetworking的AFJSONResponseSerializer(JSON响应序列化器)中的初始化init方法中的源码:
self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil];
( acceptableContentTypes表示可接受的响应的MINE类型,如果不为nil,那么当服务器响应中的Content-Type在里面找不到对应的MINE类型,AFN会在响应的校验方法中返回错误信息:- (BOOL)validateResponse:(nullable NSHTTPURLResponse *)response data:(nullable NSData *)data error:(NSError * _Nullable __autoreleasing *)error; )
服务器一般返回的几种的响应内容:
1、服务端需要返回一段普通文本给客户端,Content-Type="text/plain"
2、服务端需要返回一段HTML代码给客户端 ,Content-Type="text/html"
3、服务端需要返回一段XML代码给客户端 ,Content-Type="text/xml"
4、服务端需要返回一段javascript代码给客户端 Content-Type="text/javascript "
5、服务端需要返回一段json串给客户端 Content-Type="application/json“
因此:由于上面AFJSONResponseSerializer初始化方法代码中,只添加了对@"application/json", @"text/json", @"text/javascript" 三种类型的支持,如果需要添加对text/html类型的支持,应该在创建AFHTTPSessionManager的时候(懒加载),重新设置acceptableContentTypes(不要在源码里面添加,因为会导致pod install之后,又要重新修改),代码如下:
_manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html", nil];
综上,常规的AFN网络访问步骤如下
//实例化AFHTTPSessionManager,所有的网络请求,均有manager发起
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//如果提交数据是JSON的,需要将请求格式设置为AFJSONRequestSerializer
manager.requestSerializer = [AFJSONRequestSerializer serializer];
//如果返回格式不是JSON的,那么就根据返回数据格式修改解析器
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
//设置请求头:将token等每次请求需要带的参数封装入请求头
[manager.requestSerializer setValue:TOKEN forHTTPHeaderField:@"token-id"];
监测网络
#pragma mark - 检测网络连接
- (void)reach
{
/**
AFNetworkReachabilityStatusUnknown = -1, // 未知
AFNetworkReachabilityStatusNotReachable = 0, // 无连接
AFNetworkReachabilityStatusReachableViaWWAN = 1, // 3G 花钱
AFNetworkReachabilityStatusReachableViaWiFi = 2, // 局域网络,不花钱
*/
// 如果要检测网络状态的变化,必须用检测管理器的单例的startMonitoring
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
// 检测网络连接的单例,网络变化时的回调方法
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(@"%d", status);
}];
}
关于AFNetworking结果回调, 已经帮我们放到主线程了(以下为源码)
失败结果回调一
- (NSURLSessionDataTask *)POST:(NSString *)URLString
parameters:(id)parameters
constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
progress:(nullable void (^)(NSProgress * _Nonnull))uploadProgress
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
NSError *serializationError = nil;
NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:&serializationError];
if (serializationError) {
if (failure) {
dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
failure(nil, serializationError);
});
}
return nil;
}
失败结果回调二
- (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;
}
成功结果回调
#pragma mark - NSURLSessionTaskDelegate
- (void)URLSession:(__unused NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
__strong AFURLSessionManager *manager = self.manager;
__block id responseObject = nil;
__block NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = manager.responseSerializer;
*//Performance Improvement from #2672*
NSData *data = nil;
if (self.mutableData) {
data = [self.mutableData copy];
*//We no longer need the reference*, *so nil it out to gain back some memory.*
self.mutableData = nil;
}
if (self.downloadFileURL) {
userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self.downloadFileURL;
} else if (data) {
userInfo[AFNetworkingTaskDidCompleteResponseDataKey] = data;
}
if (error) {
userInfo[AFNetworkingTaskDidCompleteErrorKey] = error;
dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
if (self.completionHandler) {
self.completionHandler(task.response, responseObject, error);
}
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
});
});
} else {
dispatch_async(url_session_manager_processing_queue(), ^{
NSError *serializationError = nil;
responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError];
if (self.downloadFileURL) {
responseObject = self.downloadFileURL;
}
if (responseObject) {
userInfo[AFNetworkingTaskDidCompleteSerializedResponseKey] = responseObject;
}
if (serializationError) {
userInfo[AFNetworkingTaskDidCompleteErrorKey] = serializationError;
}
dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
if (self.completionHandler) {
self.completionHandler(task.response, responseObject, serializationError);
}
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
});
});
});
}
}
AFNetWorking源码之NSURLSession系列概述
https://huang303513.github.io/2017/04/14/AFNetWorking%E6%BA%90%E7%A0%81%E4%B9%8BNSURLSession%E7%B3%BB%E5%88%97%E6%A6%82%E8%BF%B0.html
AFNetworking3.0后为什么不再需要常驻线程
https://www.jianshu.com/p/b5c27669e2c1