AFNetworking對(duì)于iOS開發(fā)者來說是一個(gè)十分熟悉的網(wǎng)絡(luò)請(qǐng)求三方框架冕象,本文就是就是對(duì)這個(gè)優(yōu)秀三方框架的學(xué)習(xí)的一些總結(jié)主籍;首先看一下最新的AFNetworking結(jié)構(gòu)目錄:
AFNetworking包含的模塊
- 網(wǎng)絡(luò)請(qǐng)求模塊
- 網(wǎng)絡(luò)監(jiān)控模塊
- 安全策略模塊
- 網(wǎng)絡(luò)請(qǐng)求/響應(yīng)序列化模塊
- UIKit的擴(kuò)展模塊
AFNetworking便捷之處
AFNetworking在使用過程中僅僅需要開發(fā)者考慮,HTTP Method展氓、URL适掰、Params、回調(diào)的Block中解析響應(yīng)數(shù)據(jù)始锚、錯(cuò)誤的回調(diào)Block中處理錯(cuò)誤展示的信息;對(duì)于數(shù)據(jù)的上傳畦韭、下載疼蛾、安全策略配置等方面的支持AFNetworking更讓開發(fā)者減輕了不少開發(fā)量;
AFNetworking 的簡(jiǎn)單使用案例
-(void)requestPhoneNumberBelong{
NSURLSessionConfiguration* sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFHTTPSessionManager* sessionManager = [[AFHTTPSessionManager alloc] initWithBaseURL:nil sessionConfiguration:sessionConfiguration];
[sessionManager GET:@"http://tcc.taobao.com/cc/json/mobile_tel_segment.htm" parameters:@{@"tel":@"18518487767"} success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
NSStringEncoding gbkEncoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
NSString *pageSource = [[NSString alloc] initWithData:responseObject encoding:gbkEncoding];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
}
AFHTTPSessionManager的創(chuàng)建解析
創(chuàng)建sessionManger也是使用NSURLSessionConfiguration配置SessionConfiguration艺配,使用AFSecurityPolicy來配置安全策略;
AFNetworking網(wǎng)絡(luò)任務(wù)的創(chuàng)建是在哪個(gè)線程執(zhí)行的衍慎?
對(duì)于這個(gè)問題首先看一下網(wǎng)絡(luò)任務(wù)創(chuàng)建的代碼片段
__block NSURLSessionDataTask *dataTask = nil;
dispatch_sync(url_session_manager_creation_queue(), ^{
NSLog(@"---->%@",[NSThread currentThread]);
dataTask = [self.session dataTaskWithRequest:request];
});
// url_session_manager_creation_queue 的創(chuàng)建
static dispatch_queue_t url_session_manager_creation_queue() {
static dispatch_queue_t af_url_session_manager_creation_queue;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
af_url_session_manager_creation_queue = dispatch_queue_create("com.alamofire.networking.session.manager.creation", DISPATCH_QUEUE_SERIAL);
});
return af_url_session_manager_creation_queue;
}
使用dispatch_sync在url_session_manager_creation_queue()函數(shù)返回的serial queue中執(zhí)行request的請(qǐng)求转唉,因此AFNetworking在創(chuàng)建網(wǎng)絡(luò)任務(wù)的時(shí)候所在的線程取決于你網(wǎng)絡(luò)任務(wù)發(fā)起所在的線程(主線程或是你自己創(chuàng)建的線程中);
對(duì)于這個(gè)段代碼片段究竟有什么作用稳捆?看資料的解釋是為了解決iOS 8.0以下版本中偶發(fā)的taskIdentifiers不唯一的bug赠法;
AFNetworking網(wǎng)絡(luò)任務(wù)的完成回調(diào)是在哪個(gè)線程執(zhí)行的?
首先一段代碼片段
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;
}
代碼中如果NSMutableURLRequest的對(duì)象創(chuàng)建失敗,當(dāng)completionQueue為nil時(shí)砖织,會(huì)異步在main queue中執(zhí)行失敗回調(diào)款侵,也就是在主線程中處理錯(cuò)誤回調(diào);
當(dāng)數(shù)據(jù)請(qǐng)求完成會(huì)回調(diào)- (void)URLSession:(__unused NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
方法侧纯;此方法中存在代碼片段
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
});
所以AFNetworking在NSURLSession完成數(shù)據(jù)請(qǐng)求回調(diào)之后會(huì)在主線程里發(fā)送AFNetworkingTaskDidCompleteNotification通知新锈,即AFNetworking網(wǎng)絡(luò)任務(wù)的完成回調(diào)處理是在主線程中完成的;
AFSecurityPolicy
AFSecurityPolicy可以簡(jiǎn)化客戶端配置安全策略的工作量眶熬;AFSecurityPolicy提供了三種模式:
- AFSSLPinningModeNone:這個(gè)模式表示不做SSL pinning妹笆,只跟瀏覽器一樣在系統(tǒng)的信任機(jī)構(gòu)列表里驗(yàn)證服務(wù)端返回的證書。若證書是信任機(jī)構(gòu)簽發(fā)的就會(huì)通過娜氏,若是自己服務(wù)器生成的證書拳缠,這里是不會(huì)通過的。
- AFSSLPinningModeCertificate:這個(gè)模式表示用證書綁定方式驗(yàn)證證書贸弥,需要客戶端保存有服務(wù)端的證書拷貝窟坐,這里驗(yàn)證分兩步,第一步驗(yàn)證證書的域名/有效期等信息绵疲,第二步是對(duì)比服務(wù)端返回的證書跟客戶端返回的是否一致哲鸳。
- AFSSLPinningModePublicKey:這個(gè)模式同樣是用證書綁定方式驗(yàn)證,客戶端要有服務(wù)端的證書拷貝最岗,只是驗(yàn)證時(shí)只驗(yàn)證證書里的公鑰帕胆,不驗(yàn)證證書的有效期等信息。只要公鑰是正確的般渡,就能保證通信不會(huì)被竊聽懒豹,因?yàn)橹虚g人沒有私鑰,無法解開通過公鑰加密的數(shù)據(jù)驯用。
客戶端配置HTTPS的方式
客戶端驗(yàn)證HTTPS協(xié)議的一種方式是將把服務(wù)端證書(需要轉(zhuǎn)換成cer格式)放到APP項(xiàng)目資源里脸秽,AFSecurityPolicy會(huì)自動(dòng)尋找根目錄下所有cer文件
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];
securityPolicy.allowInvalidCertificates = YES;
[AFHTTPRequestOperationManager manager].securityPolicy = securityPolicy;
[manager GET:@"https://example.com/" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
AFNetworking2.0這個(gè)系列對(duì)源碼進(jìn)行了更詳細(xì)的解析可以參照。