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的基本使用,方便以后查找。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。