AFNetworking 3.0 使用详解 和 源码解析实现原理
AFN原理&& AFN如何使用RunLoop来实现的:
让你介绍一下AFN源码的理解,首先要说说封装里面主要做了那些重要的事情,有那些重要的类(XY题)
一、AFN的实现步骤:
NSString * requestURL = @"http://119.254.98.136/api/v1/web/homepage"; // AFHTTPSessionManager * manager =[[AFHTTPSessionManager alloc] init]; AFHTTPSessionManager * manager =[AFHTTPSessionManager manager]; [manager GET:requestURL parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSLog(@"请求成功了!"); NSLog(@"%@",responseObject); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"请求失败了!"); }];
1、GET,或者POST等方法调用抽象的请求方法,指明相应的请求参数,(类似全能初始化方法的作用一下,最后不管多少个初始化参数的方法,都最后是调用了全能初始化方法),不管是什么形式的数据请求,最后是调用了全能数据请求的方法。指明数据请求的方式以及全能的参数。
- (NSURLSessionDataTask *)GET:(NSString *)URLString parameters:(id)parameters progress:(void (^)(NSProgress * _Nonnull))downloadProgress success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure { NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:downloadProgress success:success failure:failure]; [dataTask resume]; return dataTask; }
2、对请求进行序列化,如果序列化失败,就直接执行了failure block,否则继续3
- (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) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wgnu" dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ failure(nil, serializationError); }); #pragma clang diagnostic pop } 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; }
3、为每一个NSURLSessionDataTask的dataTask增加代理
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler { __block NSURLSessionDataTask *dataTask = nil; url_session_manager_create_task_safely(^{ dataTask = [self.session dataTaskWithRequest:request]; }); [self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler]; return dataTask; }
4、对每一个NSURLSessionDataTask的dataTask增加代理的具体实现,对dataTask设置请求之后的回调Delegate和处理block
- (void)addDelegateForDataTask:(NSURLSessionDataTask *)dataTask uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler { AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init]; delegate.manager = self; delegate.completionHandler = completionHandler; dataTask.taskDescription = self.taskDescriptionForSessionTasks; [self setDelegate:delegate forTask:dataTask]; delegate.uploadProgressBlock = uploadProgressBlock; delegate.downloadProgressBlock = downloadProgressBlock; }
#pragma clang diagnostic push #pragma clang diagnostic ignored "-Wgnu" dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ failure(nil, serializationError); }); #pragma clang diagnostic pop
表示在这个区间里忽略一些特定的clang的编译警告,因为AFNetworking作为一个库被其他项目引用,所以不能全局忽略clang的一些警告,只能在有需要的时候局部这样做,作者喜欢用?:符号,所以经常见忽略-Wgnu警告的写法
NSURLConnection
是 Foundation URL 加载系统的基石。一个 NSURLConnection
异步地加载一个 NSURLRequest
对象,调用 delegate 的 NSURLResponse
/ NSHTTPURLResponse
方法,其 NSData
被发送到服务器或从服务器读取;delegate 还可用来处理 NSURLAuthenticationChallenge
、重定向响应、或是决定 NSCachedURLResponse
如何存储在共享的 NSURLCache
上。
NSOperation
是抽象类,模拟单个计算单元,有状态、优先级、依赖等功能,可以取消。
AFURLConnectionOperation将两者结合,
作为 NSOperation
的子类,遵循 NSURLConnectionDelegate
的方法,可以从头到尾监视请求的状态,并储存请求、响应、响应数据等中间状态。
创建 AFURLConnectionOperation
并把它安排进 NSOperationQueue
,通过设置 NSOperation
的新属性 completionBlock
,指定操作完成时如何处理 response 和 response data(或是请求过程中遇到的错误)。
AFNetworking 3.0 实现完全基于NSURLSessionTask进行封装,NSURLSessionTask 是苹果在iOS7 推出的网络请求api。AF支持https,网络数据请求,文件上传,文件下载,监听手机网络状态。AFHttpSessionManager 继承 AFURLSessionManager 对网络请求进行管理,使用AFURLRequestSerialization 对网络请求进行封装,使用AFURLReponseSerialization 响应体进行处理,使用AFSecurityPolicy 对服务器证书进行校验。支持https协议,支持本地证书和服务器证书进行对比验证,AF要求ios7或以上系统。AF数据传递主要使用block 和 notifacation的方式。
使用详解
AFURLSessionManager 使用方法
1、请求服务器数据
2、上传数据
3、多线程下载数据
AFHttpSessionManager 使用方法
1、post
2、get
3、上传
AFSecurityPolicy
服务器和客户端都生成相应的证书之后,iOS项目将服务器端的证书保存导入到项目中。接着AFN根据项目中的服务器的证书来进行验证。
AFSecurityPolicy对服务器的验证,保证访问服务器的安全性。(这里牵涉到Https和Http的不同,以及不同的验证方式,请求有何不同。)
证书的验证模式 AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
- AFSSLPinningModeNone
不做任何验证,只要服务器返回了证书就通过
- AFSSLPinningModePublicKey
只验证公钥部分,只要公钥部分一致就验证通过,如图所示,红色框起来的部分只要一致就通过
- AFSSLPinningModeCertificate
除了公钥外,其他能容也要一致才能通过验证。
AFURLSessionManager
AFURLSessionManager管理所有的请求,session 设置了NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate 实现证书合法性校验,数据传输进度检测,数据请求成功或失败的回调。
使用runtime 用af_supend 替换 suspend,用af_resume 替换了resume 当调用这两个方法的时候往上层发送通知AFNetworkingTaskDidSuspendNotification AFNetworkingTaskDidResumeNotification