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

前言:

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

AFNetWorking

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

下载地址:AFNetworking_jb51.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的基本使用,方便以后查找。

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

(0)

相关推荐

  • iOS应用开发中AFNetworking库的常用HTTP操作方法小结

    准备 首先,你需要将AFNetworking 框架包含到工程中.如果你还没有AFNetworking的话,在这里下载最新的版本: https://github.com/AFNetworking/AFNetworking 当你解压出下载的文件后,你将看到其中有一个AFNetworking子文件夹,里面全是.h 和 .m 文件, 如下高亮显示的: 将AFNetworking拖拽到Xcode工程中. 当出现了添加文件的选项时,确保勾选上Copy items into destination group

  • iOS利用AFNetworking3.0——实现文件断点下载

    0.导入框架准备工作 1. 将AFNetworking3.0+框架程序拖拽进项目 2. 或使用Cocopod 导入AFNetworking3.0+ 3.  引入 #import "AFNetworking.h" 1.UI准备工作 A. 定义一个全局的 NSURLSessionDownloadTask:下载管理句柄 由其负责所有的网络操作请求 @interface ViewController () { // 下载句柄 NSURLSessionDownloadTask *_downloa

  • iOS AFNetworking中cookie重定向代码

    // 1. 取出需要同步的url (登录请求中返回的重定向地址) BESTHttpItem *httpItem = [BESTHttpHelper sharedHelper].curHttpItem; NSString *url = [NSString stringWithFormat:@"%@/#/login", httpItem.frontend_addr]; // 2. 取出当前的headerFields NSDictionary *headerFields = [NSHTTPC

  • 详解iOS开发 - 用AFNetworking实现https单向验证,双向验证

    自苹果宣布2017年1月1日开始强制使用https以来,htpps慢慢成为大家讨论的对象之一,不是说此前https没有出现,只是这一决策让得开发者始料未及,博主在15年的时候就做过https的接口,深知此坑之深,原因就是自身对这方面知识不了解加上网上的资料少,除此外还有博客不知对错就互相转载,导致当时网上几乎找不到能用的代码,这一点,博主说的毫不夸张. 鉴于此,博主一直想填一下这个坑,多增加一些正确的代码,来供广大开发者使用,后来一直被搁置,经过尝试后,博主现将整理好的代码发布在这里,希望能帮到

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

    前言: 计划把公司的网络请求与业务解耦,所以想着学习一下网络请求,最近学习了NSURLSession,今天来学习一下基于NSURLSession封装的优秀开源框架AFNetWorking 3.x,之前13年做iOS开发时用的ASIHttpRequest开源框架. AFNetWorking AFNetWorking一款轻量级网络请求开源框架,基于iOS和mac os 网络进行扩展的高性能框架,大大降低了iOS开发工程师处理网络请求的难度,让iOS开发变成一件愉快的事情. 下载地址:AFNetwor

  • IOS 网络请求中设置cookie

    IOS 网络请求中设置cookie 1. ASIHTTPRequest ASIHTTPRequest 是一款极其强劲的 HTTP 访问开源项目.让简单的 API 完成复杂的功能,如:异步请求,队列请求,GZIP 压缩,缓存,断点续传,进度跟踪,上传文件,HTTP 认证. cookie的支持 如果 Cookie 存在的话,会把这些信息放在 NSHTTPCookieStorage 容器中共享,并供下次使用.你可以用 [ ASIHTTPRequest setSessionCookies:nil ] ;

  • IOS网络请求之NSURLSession使用详解

    前言: 无论是Android还是ios都离不开与服务器交互,这就必须用到网络请求,记得在2013年做iOS的时候那时候用的ASIHTTPRequest框架,现在重新捡起iOS的时候ASIHTTPRequest已经停止维护,大家都在用AFNetWorking作为首选网络请求框架,之前的ASIHTTPRequest是基于NSURLConnection类实现的,早期的AFNetWorking也是基于NSURLConnection实现,后来iOS9 之后已经放弃了NSURLConnection,开始使用

  • 浅谈IOS中AFNetworking网络请求的get和post步骤

    1.首先通过第三方:CocoaPods下载AFNetworking 1.1.先找到要查找的三方库:pod search + AFNetworking 1.2.出来一堆列表页面,选择三方库最新版本命令,例如: pod 'MBProgressHUD','~>0.8'  (:q 返回) 1.3.创建工程,进入工程: cd + 工程路径 1.4.编辑工程的Podfile文件: vim Podfile 1.5.(platform :iOS, '8.0'
target "工程名" do
po

  • 详解iOS AFNetworking取消正在进行的网络请求

    简介 项目开发时,开发人员经常会遇到一种情况,A控制器push进入B控制器,B控制器正在进行网络请求,请求未结束时,点击返回回到A控制器,现在问题出现了,B中网络请求还在执行,dealloc并未立即调用,为什么会发生这种情况?想在退出当前控制器时取消掉正在进行的请求,怎么做? 网络请求的封装 以AFNetworking为例,上我自己的网络请求封装主要代码: //单例模式 + (HttpManager *)sharedManager { static dispatch_once_t once; d

  • 详解iOS - ASIHTTPRequest 网络请求

    前言 使用 iOS SDK 中的 HTTP 网络请求 API,相当的复杂,调用很繁琐,ASIHTTPRequest 就是一个对 CFNetwork API 进行了封装,并且使用起来非常简单的一套 API,外号 "HTTP终结者",用 Objective-C 编写,运行效率很高,可以很好的应用在 Mac OS X 系统和 iOS 平台的应用程序中,ASIHTTPRequest 适用于基本的 HTTP 请求,和基于 REST 的服务之间的交互.可惜作者早已停止更新,有一些潜在的 BUG 无

  • 详解如何拦截iOS所有网络请求

    背景 最近在研究iOS无埋点统计技术,我们的统计SDK主要分两部分:点击事件和网络请求.统计所有的点击事件是采用Method Swizzling实现的,可以做到使用中不需要一行代码实现统计所有事件,具体细节将来我会专门抽几篇文章介绍. 今天主要说说如何统计APP中的所有网络请求.公司网络请求如果不是静态库或者框架,很容易想到在网络请求发送和返回时添加统计的代码.如何在不修改原来代码(或者修改最少)的基础上拦截所有的请求呢,能不能从系统层面上拦截回调呢?答案是肯定的,苹果有一个黑魔法NSURLPr

  • iOS中多网络请求的线程安全详解

    前言 在iOS 网络编程有一种常见的场景是:我们需要并行处理二个请求并且在都成功后才能进行下一步处理.下面是部分常见的处理方式,但是在使用过程中也很容易出错: DispatchGroup:通过 GCD 机制将多个请求放到一个组内,然后通过 DispatchGroup.wait() 和 DispatchGroup.notify() 进行成功后的处理. OperationQueue:为每一个请求实例化一个 Operation 对象,然后将这些对象添加到 OperationQueue ,并且根据它们之

  • iOS判断网络请求超时的方法

    本文介绍了iOS判断网络请求超时的方法,代码具体如下: + (AFHTTPRequestOperation *)requestOperationWithUrl:(NSString *)url requetMethod:(NSString *)method paramData:(NSDictionary *)aParamData constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block success

  • IOS开发中异步网络请求上实现同步逻辑

    IOS开发中异步网络请求上实现同步逻辑 前提: 可能遇到一些问题,比如上传多个数据,需要等多个数据上传成功后做一定的处理,而且一个个上传,万一哪个上传失败了,后面就不需要上传了,直接报错. 之前ASI的网络库中是有同步请求的接口,所以很好处理,AFNetwork的网络库只有异步的网络请求,该怎么实现呢? 1.循环异步拼组 - (void)uploadFile:(NSArray *)imageArray atIndex:(NSInteger)index imagesCount:(NSInteger

随机推荐