IOS网络请求之AFNetWorking 3.x 使用详情
前言:
计划把公司的网络请求与业务解耦,所以想着学习一下网络请求,最近学习了NSURLSession,今天来学习一下基于NSURLSession封装的优秀开源框架AFNetWorking3.x,之前13年做iOS开发时用的ASIHttpRequest开源框架。
AFNetWorking
AFNetWorking一款轻量级网络请求开源框架,基于iOS和macos网络进行扩展的高性能框架,大大降低了iOS开发工程师处理网络请求的难度,让iOS开发变成一件愉快的事情。
下载地址:AFNetworking_jb51.rar
1.)AFHTTPSessionManager请求管理者
-(AFHTTPSessionManager*)sharedManager { AFHTTPSessionManager*manager=[AFHTTPSessionManagermanager]; //最大请求并发任务数 manager.operationQueue.maxConcurrentOperationCount=5; //请求格式 //AFHTTPRequestSerializer二进制格式 //AFJSONRequestSerializerJSON //AFPropertyListRequestSerializerPList(是一种特殊的XML,解析起来相对容易) manager.requestSerializer=[AFHTTPRequestSerializerserializer];//上传普通格式 //超时时间 manager.requestSerializer.timeoutInterval=30.0f; //设置请求头 [manager.requestSerializersetValue:@"gzip"forHTTPHeaderField:@"Content-Encoding"]; //设置接收的Content-Type manager.responseSerializer.acceptableContentTypes=[[NSSetalloc]initWithObjects:@"application/xml",@"text/xml",@"text/html",@"application/json",@"text/plain",nil]; //返回格式 //AFHTTPResponseSerializer二进制格式 //AFJSONResponseSerializerJSON //AFXMLParserResponseSerializerXML,只能返回XMLParser,还需要自己通过代理方法解析 //AFXMLDocumentResponseSerializer(MacOSX) //AFPropertyListResponseSerializerPList //AFImageResponseSerializerImage //AFCompoundResponseSerializer组合 manager.responseSerializer=[AFJSONResponseSerializerserializer];//返回格式JSON //设置返回C的ontent-type manager.responseSerializer.acceptableContentTypes=[[NSSetalloc]initWithObjects:@"application/xml",@"text/xml",@"text/html",@"application/json",@"text/plain",nil]; returnmanager; }
2.)处理get请求
-(void)doGetRequest { //创建请求地址 NSString*url=@"http://api.nohttp.net/method"; //构造参数 NSDictionary*parameters=@{@"name":@"yanzhenjie",@"pwd":@"123"}; //AFN管理者调用get请求方法 [[selfshareAFNManager]GET:urlparameters:parametersprogress:^(NSProgress*_NonnulldownloadProgress){ //返回请求返回进度 NSLog(@"downloadProgress-->%@",downloadProgress); }success:^(NSURLSessionDataTask*_Nonnulltask,id_NullableresponseObject){ //请求成功返回数据根据responseSerializer返回不同的数据格式 NSLog(@"responseObject-->%@",responseObject); }failure:^(NSURLSessionDataTask*_Nullabletask,NSError*_Nonnullerror){ //请求失败 NSLog(@"error-->%@",error); }]; }
3.)处理post请求
-(void)doPostRequestOfAFN { //创建请求地址 NSString*url=@"http://api.nohttp.net/postBody"; //构造参数 NSDictionary*parameters=@{@"name":@"yanzhenjie",@"pwd":@"123"}; //AFN管理者调用get请求方法 [[selfshareAFNManager]POST:urlparameters:parametersprogress:^(NSProgress*_NonnulluploadProgress){ //返回请求返回进度 NSLog(@"downloadProgress-->%@",uploadProgress); }success:^(NSURLSessionDataTask*_Nonnulltask,id_NullableresponseObject){ //请求成功返回数据根据responseSerializer返回不同的数据格式 NSLog(@"responseObject-->%@",responseObject); }failure:^(NSURLSessionDataTask*_Nullabletask,NSError*_Nonnullerror){ //请求失败 NSLog(@"error-->%@",error); }]; }
4.)处理文件上传
-(void)doUploadRequest { //创建URL资源地址 NSString*url=@"http://api.nohttp.net/upload"; //参数 NSDictionary*parameters=@{@"name":@"yanzhenjie",@"pwd":@"123"}; [[selfshareAFNManager]POST:urlparameters:parametersconstructingBodyWithBlock:^(id<AFMultipartFormData>_NonnullformData){ NSDate*dat=[NSDatedateWithTimeIntervalSinceNow:0]; NSTimeIntervala=[dattimeIntervalSince1970]; NSString*fileName=[NSStringstringWithFormat:@"file_%0.f.txt",a]; [FileUtilswriteDataToFile:fileNamedata:[@"upload_file_to_server"dataUsingEncoding:NSUTF8StringEncoding]]; //获取数据转换成data NSString*filePath=[FileUtilsgetFilePath:fileName]; //拼接数据到请求题中 [formDataappendPartWithFileURL:[NSURLfileURLWithPath:filePath]name:@"headUrl"fileName:fileNamemimeType:@"application/octet-stream"error:nil]; }progress:^(NSProgress*_NonnulluploadProgress){ //上传进度 NSLog(@"%lf",1.0*uploadProgress.completedUnitCount/uploadProgress.totalUnitCount); }success:^(NSURLSessionDataTask*_Nonnulltask,id_NullableresponseObject){ //请求成功 NSLog(@"请求成功:%@",responseObject); }failure:^(NSURLSessionDataTask*_Nullabletask,NSError*_Nonnullerror){ //请求失败 NSLog(@"请求失败:%@",error); }]; }
5.)处理文件下载
-(void)doDownLoadRequest { NSString*urlStr=@"http://images2015.cnblogs.com/blog/950883/201701/950883-20170105104233581-62069155.png"; //设置请求的URL地址 NSURL*url=[NSURLURLWithString:urlStr]; //创建请求对象 NSURLRequest*request=[NSURLRequestrequestWithURL:url]; //下载任务 NSURLSessionDownloadTask*task=[[selfshareAFNManager]downloadTaskWithRequest:requestprogress:^(NSProgress*_NonnulldownloadProgress){ //下载进度 NSLog(@"当前下载进度为:%lf",1.0*downloadProgress.completedUnitCount/downloadProgress.totalUnitCount); }destination:^NSURL*_Nonnull(NSURL*_NonnulltargetPath,NSURLResponse*_Nonnullresponse){ //下载地址 NSLog(@"默认下载地址%@",targetPath); //这里模拟一个路径真实场景可以根据url计算出一个md5值作为fileKey NSDate*dat=[NSDatedateWithTimeIntervalSinceNow:0]; NSTimeIntervala=[dattimeIntervalSince1970]; NSString*fileKey=[NSStringstringWithFormat:@"/file_%0.f.txt",a]; //设置下载路径,通过沙盒获取缓存地址,最后返回NSURL对象 NSString*filePath=[FileUtilsgetFilePath:fileKey]; return[NSURLfileURLWithPath:filePath];//返回的是文件存放在本地沙盒的地址 }completionHandler:^(NSURLResponse*_Nonnullresponse,NSURL*_NullablefilePath,NSError*_Nullableerror){ //下载完成调用的方法 NSLog(@"filePath---%@",filePath); NSData*data=[NSDatadataWithContentsOfURL:filePath]; UIImage*image=[UIImageimageWithData:data]; //刷新界面... UIImageView*imageView=[[UIImageViewalloc]init]; imageView.image=image; [self.viewaddSubview:imageView]; [imageViewmas_makeConstraints:^(MASConstraintMaker*make){ make.center.equalTo(self.view); make.size.mas_equalTo(CGSizeMake(300,300)); }]; }]; //启动下载任务 [taskresume]; }
6.)网络状态监听
-(void)aFNetworkStatus{ //创建网络监测者 AFNetworkReachabilityManager*manager=[AFNetworkReachabilityManagersharedManager]; /*枚举里面四个状态分别对应未知无网络数据WiFi typedefNS_ENUM(NSInteger,AFNetworkReachabilityStatus){ AFNetworkReachabilityStatusUnknown=-1,未知 AFNetworkReachabilityStatusNotReachable=0,无网络 AFNetworkReachabilityStatusReachableViaWWAN=1,蜂窝数据网络 AFNetworkReachabilityStatusReachableViaWiFi=2,WiFi }; */ [managersetReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatusstatus){ //这里是监测到网络改变的block可以写成switch方便 //在里面可以随便写事件 switch(status){ caseAFNetworkReachabilityStatusUnknown: NSLog(@"未知网络状态"); break; caseAFNetworkReachabilityStatusNotReachable: NSLog(@"无网络"); break; caseAFNetworkReachabilityStatusReachableViaWWAN: NSLog(@"蜂窝数据网"); break; caseAFNetworkReachabilityStatusReachableViaWiFi: NSLog(@"WiFi网络"); break; default: break; } }]; [managerstartMonitoring]; }
AFNetWorking内存泄露
通常情况我们一般会认为以manager结尾的都是单例模式,所以我们一般都是这样使用AFNetWorking,如下
AFHTTPSessionManager*manager=[AFHTTPSessionManagermanager];
其实我们点进去查看源码发现并不是单例,而是每次都实例化一个AFHTTPSessionManager对象,源码如下
+(instancetype)manager{ return[[[selfclass]alloc]initWithBaseURL:nil]; }
所以我们在使用AFNetWorking的时候要对AFHTTPSessionManager进行单例封装
+(AFHTTPSessionManager*)sharedManager { staticAFHTTPSessionManager*manager=nil; staticdispatch_once_tpredicate; dispatch_once(&predicate,^{ manager=[AFHTTPSessionManagermanager]; manager.operationQueue.maxConcurrentOperationCount=5; manager.requestSerializer.timeoutInterval=30.f; manager.responseSerializer.acceptableContentTypes=[[NSSetalloc]initWithObjects:@"application/xml",@"text/xml",@"text/html",@"application/json",@"text/plain",nil]; [manager.requestSerializersetValue:@"gzip"forHTTPHeaderField:@"Content-Encoding"]; }); returnmanager; }
AFNetWorking关于HTTPS
在2017年1月1日起Apple要求开发者于年底之前为提交至AppStore中的应用启用HTTPS,以支持iOS9引入的ATS(AppTransportSecurity)技术。但后来,apple发布声明宣布延长这个时限,提供给开发者更多的时间进行相关准备。目前Apple尚未公布新的截止日期。所以目前应对https的方案有两种。
第一种方式:
屏蔽调iOSATS(AppTransportSecurity),在pList.info文件中添加如下代码
<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>
第二种方式:
配置httpsCA证书,这里采用获取NSBundle中获取CA证书,AFNetWorking提供了配置AFSecurityPolicy模块
+(AFSecurityPolicy*)customSecurityPolicy{ //HttpsCA证书地址 NSString*cerPath=[[NSBundlemainBundle]pathForResource:@"XueLeTSHTTPS"ofType:@"cer"]; //获取CA证书数据 NSData*cerData=[NSDatadataWithContentsOfFile:cerPath]; //创建AFSecurityPolicy对象 AFSecurityPolicy*security=[AFSecurityPolicypolicyWithPinningMode:AFSSLPinningModeNone]; //设置是否允许不信任的证书(证书无效、证书时间过期)通过验证,默认为NO. security.allowInvalidCertificates=YES; //是否验证域名证书的CN(commonname)字段。默认值为YES。 security.validatesDomainName=NO; //根据验证模式来返回用于验证服务器的证书 security.pinnedCertificates=[NSSetsetWithObject:cerData]; returnsecurity; }
然后通过设置AFHTTPSessionManager的securityPolicy属性等于自定义的AFSecurityPolicy。
总结:
简单记录一下AFNetWorking的基本使用,方便以后查找。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。