前言:计划把公司的网络请求与业务解耦,所以想着学习一下网络请求,最近学习了NSURLSession,今天来学习一下基于NSURLSession封装的优秀开源框架AFNetWorking 3.x,之前13年做iOS开发时用的ASIHttpRequest开源框架。
AFNetWorkingAFNetWorking一款轻量级网络请求开源框架,基于iOS和mac os 网络进行扩展的高性能框架,大大降低了iOS开发工程师处理网络请求的难度,让iOS开发变成一件愉快的事情。
下载地址:AFNetworking_jb51.rar
1.)AFHTTPSessionManager请求管理者
-(AFHTTPSessionManager *)sharedManager{AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];//最大请求并发任务数manager.operationQueue.maxConcurrentOperationCount = 5;// 请求格式// AFHTTPRequestSerializer二进制格式// AFJSONRequestSerializerJSON// AFPropertyListRequestSerializerPList(是一种特殊的XML,解析起来相对容易)manager.requestSerializer = [AFHTTPRequestSerializer serializer]; // 上传普通格式// 超时时间manager.requestSerializer.timeoutInterval = 30.0f;// 设置请求头[manager.requestSerializer setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"];// 设置接收的Content-Typemanager.responseSerializer.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"application/xml", @"text/xml",@"text/html", @"application/json",@"text/plain",nil];// 返回格式// AFHTTPResponseSerializer二进制格式// AFJSONResponseSerializerJSON// AFXMLParserResponseSerializer XML,只能返回XMLParser,还需要自己通过代理方法解析// AFXMLDocumentResponseSerializer (Mac OS X)// AFPropertyListResponseSerializerPList// AFImageResponseSerializer Image// AFCompoundResponseSerializer组合manager.responseSerializer = [AFJSONResponseSerializer serializer];//返回格式 JSON//设置返回C的ontent-typemanager.responseSerializer.acceptableContentTypes=[[NSSet alloc] initWithObjects:@"application/xml", @"text/xml",@"text/html", @"application/json",@"text/plain",nil];return manager;}
2.)处理get请求
-(void)doGetRequest{//创建请求地址NSString *url=@"http://api.nohttp.net/method";//构造参数NSDictionary *parameters=@{@"name":@"yanzhenjie",@"pwd":@"123"};//AFN管理者调用get请求方法[[self shareAFNManager] GET:url parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) {//返回请求返回进度NSLog(@"downloadProgress-->%@",downloadProgress);} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {//请求成功返回数据 根据responseSerializer 返回不同的数据格式NSLog(@"responseObject-->%@",responseObject);} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {//请求失败NSLog(@"error-->%@",error);}];}
3.)处理post请求
-(void)doPostRequestOfAFN{//创建请求地址NSString *url=@"http://api.nohttp.net/postBody";//构造参数NSDictionary *parameters=@{@"name":@"yanzhenjie",@"pwd":@"123"};//AFN管理者调用get请求方法[[self shareAFNManager] POST:url parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {//返回请求返回进度NSLog(@"downloadProgress-->%@",uploadProgress);} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {//请求成功返回数据 根据responseSerializer 返回不同的数据格式NSLog(@"responseObject-->%@",responseObject);} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {//请求失败NSLog(@"error-->%@",error);}];}
4.)处理文件上传
-(void)doUploadRequest{// 创建URL资源地址NSString *url = @"http://api.nohttp.net/upload";// 参数NSDictionary *parameters=@{@"name":@"yanzhenjie",@"pwd":@"123"};[[self shareAFNManager] POST:url parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {NSDate* dat = [NSDate dateWithTimeIntervalSinceNow:0];NSTimeInterval a=[dat timeIntervalSince1970];NSString* fileName = [NSString stringWithFormat:@"file_%0.f.txt", a];[FileUtils writeDataToFile:fileName data:[@"upload_file_to_server" dataUsingEncoding:NSUTF8StringEncoding]];// 获取数据转换成dataNSString *filePath =[FileUtils getFilePath:fileName];// 拼接数据到请求题中[formData appendPartWithFileURL:[NSURL fileURLWithPath:filePath] name:@"headUrl" fileName:fileName mimeType:@"application/octet-stream" error:nil];} progress:^(NSProgress * _Nonnull uploadProgress) {// 上传进度NSLog(@"%lf",1.0 *uploadProgress.completedUnitCount / uploadProgress.totalUnitCount);} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {//请求成功NSLog(@"请求成功:%@",responseObject);} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {//请求失败NSLog(@"请求失败:%@",error);}];}
5.)处理文件下载
-(void)doDownLoadRequest{NSString *urlStr =@"http://images2015.cnblogs.com/blog/950883/201701/950883-20170105104233581-62069155.png";// 设置请求的URL地址NSURL *url = [NSURL URLWithString:urlStr];// 创建请求对象NSURLRequest *request = [NSURLRequest requestWithURL:url];// 下载任务NSURLSessionDownloadTask *task = [[self shareAFNManager] downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {// 下载进度NSLog(@"当前下载进度为:%lf", 1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount);} destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {// 下载地址NSLog(@"默认下载地址%@",targetPath);//这里模拟一个路径 真实场景可以根据url计算出一个md5值 作为fileKeyNSDate* dat = [NSDate dateWithTimeIntervalSinceNow:0];NSTimeInterval a=[dat timeIntervalSince1970];NSString* fileKey = [NSString stringWithFormat:@"/file_%0.f.txt", a];// 设置下载路径,通过沙盒获取缓存地址,最后返回NSURL对象NSString *filePath = [FileUtils getFilePath:fileKey];return [NSURL fileURLWithPath:filePath]; // 返回的是文件存放在本地沙盒的地址} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {// 下载完成调用的方法NSLog(@"filePath---%@", filePath);NSData *data=[NSData dataWithContentsOfURL:filePath];UIImage *image=[UIImage imageWithData:data];// 刷新界面...UIImageView *imageView =[[UIImageView alloc]init];imageView.image=image;[self.view addSubview:imageView];[imageView mas_makeConstraints:^(MASConstraintMaker *make) {make.center.equalTo(self.view);make.size.mas_equalTo(CGSizeMake(300, 300));}];}];//启动下载任务[task resume];}
6.)网络状态监听
- (void)aFNetworkStatus{//创建网络监测者AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];/*枚举里面四个状态 分别对应 未知 无网络 数据 WiFi typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { AFNetworkReachabilityStatusUnknown = -1, 未知 AFNetworkReachabilityStatusNotReachable = 0,无网络 AFNetworkReachabilityStatusReachableViaWWAN = 1,蜂窝数据网络 AFNetworkReachabilityStatusReachableViaWiFi = 2,WiFi }; */[manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {//这里是监测到网络改变的block 可以写成switch方便//在里面可以随便写事件switch (status) {case AFNetworkReachabilityStatusUnknown:NSLog(@"未知网络状态");break;case AFNetworkReachabilityStatusNotReachable:NSLog(@"无网络");break;case AFNetworkReachabilityStatusReachableViaWWAN:NSLog(@"蜂窝数据网");break;case AFNetworkReachabilityStatusReachableViaWiFi:NSLog(@"WiFi网络");break;default:break;}}] ;[manager startMonitoring];}
AFNetWorking内存泄露 通常情况我们一般会认为以manager结尾的都是单例模式,所以我们一般都是这样使用AFNetWorking,如下
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
其实我们点进去查看源码发现并不是单例,而是每次都实例化一个AFHTTPSessionManager对象,源码如下
+ (instancetype)manager {return [[[self class] alloc] initWithBaseURL:nil];}
所以我们在使用AFNetWorking的时候要对AFHTTPSessionManager进行单例封装
+ (AFHTTPSessionManager *)sharedManager{static AFHTTPSessionManager *manager = nil;static dispatch_once_t predicate;dispatch_once(&predicate, ^{manager = [AFHTTPSessionManager manager];manager.operationQueue.maxConcurrentOperationCount = 5;manager.requestSerializer.timeoutInterval=30.f;manager.responseSerializer.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"application/xml", @"text/xml",@"text/html", @"application/json",@"text/plain",nil];[manager.requestSerializer setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"];});return manager;}
AFNetWorking关于HTTPS 在2017年1月1日起Apple 要求开发者于年底之前为提交至 App Store 中的应用启用 HTTPS ,以支持 iOS 9 引入的 ATS(App Transport Security)技术。但后来,apple 发布声明宣布延长这个时限,提供给开发者更多的时间进行相关准备。目前 Apple 尚未公布新的截止日期。所以目前应对https的方案有两种。
第一种方式:
屏蔽调iOS ATS(App Transport Security),在pList.info文件中添加如下代码
<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/></dict>
第二种方式:
配置https CA证书,这里采用获取NSBundle中获取CA证书,AFNetWorking提供了配置AFSecurityPolicy模块
+ (AFSecurityPolicy *)customSecurityPolicy{//Https CA证书地址NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"XueLeTSHTTPS" ofType:@"cer"];//获取CA证书数据NSData *cerData = [NSData dataWithContentsOfFile:cerPath];//创建AFSecurityPolicy对象AFSecurityPolicy *security = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];//设置是否允许不信任的证书(证书无效、证书时间过期)通过验证 ,默认为NO.security.allowInvalidCertificates = YES;//是否验证域名证书的CN(common name)字段。默认值为YES。security.validatesDomainName = NO;//根据验证模式来返回用于验证服务器的证书security.pinnedCertificates = [NSSet setWithObject:cerData];return security;}
然后通过设置AFHTTPSessionManager的securityPolicy属性等于自定义的AFSecurityPolicy。
总结:简单记录一下AFNetWorking的基本使用,方便以后查找。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。