首页 > 系统 > iOS > 正文

IOS网络请求之AFNetWorking 3.x 使用详情

2019-10-21 18:48:30
字体:
来源:转载
供稿:网友

前言:

计划把公司的网络请求与业务解耦,所以想着学习一下网络请求,最近学习了NSURLSession,今天来学习一下基于NSURLSession封装的优秀开源框架AFNetWorking 3.x,之前13年做iOS开发时用的ASIHttpRequest开源框架。

AFNetWorking

AFNetWorking一款轻量级网络请求开源框架,基于iOS和mac os 网络进行扩展的高性能框架,大大降低了iOS开发工程师处理网络请求的难度,让iOS开发变成一件愉快的事情。

下载地址:AFNetworking.rar

1.)AFHTTPSessionManager请求管理者

-(AFHTTPSessionManager *)sharedManager{  AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];  //最大请求并发任务数  manager.operationQueue.maxConcurrentOperationCount = 5;  // 请求格式  // AFHTTPRequestSerializer      二进制格式  // AFJSONRequestSerializer      JSON  // AFPropertyListRequestSerializer  PList(是一种特殊的XML,解析起来相对容易)    manager.requestSerializer = [AFHTTPRequestSerializer serializer]; // 上传普通格式    // 超时时间  manager.requestSerializer.timeoutInterval = 30.0f;  // 设置请求头  [manager.requestSerializer setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"];  // 设置接收的Content-Type  manager.responseSerializer.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"application/xml", @"text/xml",@"text/html", @"application/json",@"text/plain",nil];    // 返回格式  // AFHTTPResponseSerializer      二进制格式  // AFJSONResponseSerializer      JSON  // AFXMLParserResponseSerializer   XML,只能返回XMLParser,还需要自己通过代理方法解析  // AFXMLDocumentResponseSerializer (Mac OS X)  // AFPropertyListResponseSerializer  PList  // AFImageResponseSerializer     Image  // AFCompoundResponseSerializer    组合    manager.responseSerializer = [AFJSONResponseSerializer serializer];//返回格式 JSON  //设置返回C的ontent-type  manager.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]];    // 获取数据转换成data    NSString *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值 作为fileKey    NSDate* 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的基本使用,方便以后查找。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VEVB武林网。


注:相关教程知识阅读请移步到IOS开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表