详解iOS - ASIHTTPRequest 网络请求
前言
使用 ios sdk 中的 http 网络请求 api,相当的复杂,调用很繁琐,asihttprequest 就是一个对 cfnetwork api 进行了封装,并且使用起来非常简单的一套 api,外号 “http终结者”,用 objective-c 编写,运行效率很高,可以很好的应用在 mac os x 系统和 ios 平台的应用程序中,asihttprequest 适用于基本的 http 请求,和基于 rest 的服务之间的交互。可惜作者早已停止更新,有一些潜在的 bug 无人去解决,很多公司的旧项目里面都残留着它的身影,以前的很多 ios 项目都是 asi + sbjson,会不会用 asi,可以算是检验是否为老牌 ios 程序员的标准之一。从 ios 9 开始 cfnetwork 相关的类和方法开始被废弃,可以使用 afnetworking 替换 asihttprequest 的使用。在 ios 9+ 中使用 asihttprequest 无需对 app transport security settings 添加设置。
1、asihttprequest
1.1 asi 主要特色
- 通过简单的接口,即可完成向服务端提交数据和从服务端获取数据的工作。
- 下载的数据,可存储到内存中或直接存储到磁盘中。
- 能上传本地文件到服务端。
- 可以方便的访问和操作请求和返回的 http 头信息。
- 可以获取到上传或下载的进度信息,为应用程序提供更好的体验。
- 支持上传或下载队列,并且可获取队列的进度信息。
- 支持基本、摘要和 ntlm 身份认证,在同一会话中授权凭证会自动维持,并且可以存储在 keychain(mac 和 ios 操作系统的密码管理系统)中。
- 支持 cookie。
- 当应用(ios 4+)在后台运行时,请求可以继续运行。
- 支持 gzip 压缩数据。
- 内置的 asidownloadcache 类,可以缓存请求返回的数据,这样即使没有网络也可以返回已经缓存的数据结果。
- asiwebpagerequest 可以下载完整的网页,包括包含的网页、样式表、脚本等资源文件,并显示在 uiwebview /webview 中。任意大小的页面都可以无限期缓存,这样即使没有网络也可以离线浏览。
- 支持客户端证书。
- 支持通过代理发起 http 请求。
- 支持带宽限制。在 ios 平台,可以根据当前网络情况来自动决定是否限制带宽,例如当使用 wwan(gprs/edge/3g) 网络时限制,而当使用 wifi 时不做任何限制。
- 支持断点续传。
- 支持同步和异步请求。
1.2 afn 与 asi 的区别
1、底层实现
1)afn 的底层实现基于 oc 的 nsurlconnection 和 nsurlsession
2)asi 的底层实现基于纯 c 语言的 cfnetwork 框架
3)因为 nsurlconnection 和 nsurlsession 是在 cfnetwork 之上的一层封装,因此 asi 的运行性能高于 afn
2、对服务器返回的数据处理
1)asi 没有直接提供对服务器数据处理的方式,直接返回的是 nsdata/nsstring
2)afn 提供了多种对服务器数据处理的方式 (1) json 处理-直接返回 nsdictionary 或者 nsarray
(2) xml 处理-返回的是 xml 类型数据,需对其进行解析
(3) 其他类型数据处理
3、监听请求过程 1
)afn 提供了success 和 failure 两个 block 来监听请求的过程(只能监听成功和失败)
- success : 请求成功后调用
- failure : 请求失败后调用
2)asi 提供了 3 套方案,每一套方案都能监听请求的完整过程(监听请求开始、接收到响应头信息、接受到具体数据、接受完毕、请求失败)
- 成为代理,遵守协议,实现协议中的代理方法
- 成为代理,不遵守协议,自定义代理方法
- 设置 block
4、在文件下载和文件上传的使用难易度
1)afn
- 不容易实现监听下载进度和上传进度
- 不容易实现断点续传
- 一般只用来下载不大的文件
2)asi
- 非常容易实现下载和上传
- 非常容易监听下载进度和上传进度
- 非常容易实现断点续传
- 下载大文件或小文件均可
3)实现下载上传推荐使用 asi
5、网络监控
1)afn 自己封装了网络监控类,易使用
2)asi 使用的是 reachability,因为使用 cocoapods 下载 asi 时,会同步下载 reachability,但 reachability 作为网络监控使用较为复杂(相对于 afn 的网络监控类来说)
3)推荐使用 afn 做网络监控 afnetworkreachabilitymanager
6、asi 提供的其他实用功能
1)控制信号旁边的圈圈要不要在请求过程中转
2)可以轻松地设置请求之间的依赖:每一个请求都是一个 nsoperation 对象
3)可以统一管理所有请求(还专门提供了一个叫做 asinetworkqueue 来管理所有的请求对象) 暂停/恢复/取消所有的请求
监听整个队列中所有请求的下载进度和上传进度
2、asihttprequest 的使用
2.1 添加 asihttprequest
github 网址:
https://allseeing-i.com/asihttprequest/
asihttprequest 系统需求:
asihttprequest version | minimum ios target | target notes |
---|---|---|
1.8.1 -> 1.8.2 | ios 3.0+ | |
0.2 -> 1.8.0 |
asihttprequest 使用 mrc
objective-c
// 添加系统库文件 cfnetwork.framework systemconfiguration.framework mobilecoreservices.framework coregraphics.framework libz.1.1.3.tbd libxml2.2.tbd // 添加第三方库文件 asihttprequest-1.8.2 // 在 targets -> builed settings -> search paths -> header search paths 中添加文件路径 /usr/include/libxml2 // 在 targets -> build phases -> compile sources -> ...in .../asihttprequest 后添加 -fno-objc-arc // 包含头文件 #import "asihttprequest.h" #import "asiformdatarequest.h"
2.2 asihttprequest 的设置
objective-c
// 设置请求头 asihttprequest *request = [asihttprequest requestwithurl:[nsurl urlwithstring:@"http://api.hudong.com/iphonexml.do?type=focus-c"]]; [request addrequestheader:@"referer" value:@"http://www.dreamingwish.com/"]; // 设置应用后台运行时是否仍然请求数据 request.shouldcontinuewhenappentersbackground = yes; // 设置请求超时时重试的次数 request.numberoftimestoretryontimeout = 3; // 设置 keepalive 支持 // set the amount of time to hang on to a persistent connection before it should expire to 2 minutes request.persistentconnectiontimeoutseconds = 120; // disable persistent connections entirely request.shouldattemptpersistentconnection = no; // 设置是否显示网络请求信息在 status bar 上 [asihttprequest setshouldupdatenetworkactivityindicator:no]; // 网络状态检查 bool isnetworkinuse = [asihttprequest isnetworkinuse];
3、asi 同步 get 请求
这是 asihttprequest 最简单的一种使用模式,发送 startsynchronous 消息后即开始在同一线程中执行 http 请求,线程将一直等待直到请求结束(请求成功或者失败)。通过检查 error 属性可以判断请求是否成功或者有错误发生。
要获取返回的文本信息,调用 responsestring 方法。如果下载的是二进制文件,例如图片、mp3,则调用 responsedata 方法,可以得到一个 nsdata 对象。
一般情况下,应该优先使用异步请求代替同步请求,当在主线程中使用 asihttprequest 同步请求会阻塞主线程的执行,这导致用户界面不响应用户操作,任何动画都会停止渲染,直到请求完成。
objective-c
数据请求
nsurl *url = [nsurl urlwithstring:@"http://api.hudong.com/iphonexml.do?type=focus-c"]; // 创建请求 asihttprequest *request = [asihttprequest requestwithurl:url]; // 设置超时时间,可不设置,使用默认 request.timeoutseconds = 5; // 发送同步请求 [request startsynchronous]; // 获得错误信息 nserror *error = [request error]; // 网络请求失败 if (error) { // 网络请求成功 nslog(@"网络请求失败:\n%@", error); } else { // 获得服务器的响应,字符串格式 nsstring *responsestring = [request responsestring]; nslog(@"网络请求成功:\n%@", responsestring); // 获得服务器的响应,nsdata 格式 nsdata *responsedata = [request responsedata]; textview.text = [[nsstring alloc] initwithdata:responsedata encoding:nsutf8stringencoding]; }
文件下载
通过设置 request 的 setdownloaddestinationpath,可以设置下载文件用的下载目标目录。首先,下载过程文件会保存在 temporaryfiledownloadpath 目录下。如果下载完成会做以下事情:
1,如果数据是压缩的,进行解压,并把文件放在 downloaddestinationpath 目录中,临时文件被删除。
2,如果下载失败,临时文件被直接移到 downloaddestinationpath 目录,并替换同名文件。
如果你想获取下载中的所有数据,可以实现 delegate 中的 request:didreceivedata:方法。但如果你实现了这个方法,request 在下载完后,request 并不把文件放在 downloaddestinationpath中,需要手工处理。
nsurl *url = [nsurl urlwithstring:@"http://www.dreamingwish.com/wp-content/uploads/2011/10/asihttprequest-auth.png"]; asihttprequest *request = [asihttprequest requestwithurl:url]; // 设置文件存储路径 [request setdownloaddestinationpath:@"/users/jhq0228/desktop/asi.png"]; [request startsynchronous]; // 获得错误信息 nserror *error = [request error]; // 网络请求失败 if (error) { nslog(@"网络请求失败:\n%@", error); } else { // 网络请求成功 nslog(@"网络请求成功:\n"); }
4、asi 异步 get 请求
请求在后台线程中运行,当请求执行完后再通知调用的线程。这样不会导致主线程进行网络请求时,界面被锁定等情况。
1、协议方式
在这里实现了两个 delegate 的方法,当数据请求成功时会调用 requestfinished,请求失败时(如网络问题或服务器内部错误)会调用 requestfailed。
nsurl *url = [nsurl urlwithstring:@"http://api.hudong.com/iphonexml.do?type=focus-c"]; // 创建请求 asihttprequest *request = [asihttprequest requestwithurl:url]; // 设置超时时间,可不设置,使用默认 request.timeoutseconds = 5; // 设置代理,需遵守 <asihttprequestdelegate> 协议 request.delegate = self; // 发送异步请求 [request startasynchronous]; // 网络请求成功,协议方法 - (void)requestfinished:(asihttprequest *)request { } // 网络请求失败,协议方法 - (void)requestfailed:(asihttprequest *)request { }
2、block 方式
在平台支持情况下,asihttprequest 1.8 以上支持 block。
nsurl *url = [nsurl urlwithstring:@"http://api.hudong.com/iphonexml.do?type=focus-c"]; // 创建请求,加 __weak 除去 block 循环调用警告 __weak asihttprequest *request = [asihttprequest requestwithurl:url]; // 设置超时时间,可不设置,使用默认 request.timeoutseconds = 5; // 发送异步请求 [request startasynchronous]; // 网络请求成功 [request setcompletionblock:^{ }]; // 网络请求失败 [request setfailedblock:^{ }];
5、asi post 请求
1、post 表单
asiformdatarequest,模拟 form 表单提交,其提交格式与 header 会自动识别。文件中的数据是需要时才从磁盘加载,所以只要 web server 能处理,那么上传大文件是没有问题的。
// 通常数据是以 'application/x-www-form-urlencoded' 格式发送的,如果上传了二进制数据或者文件,那么格式将自动变为 ‘multipart/form-data'。 asiformdatarequest *request = [asiformdatarequest requestwithurl:[nsurl urlwithstring:@"http://www.dreamingwish.com"]]; // 没有文件 [request setpostvalue:@"ben" forkey:@"first_name"]; [request setpostvalue:@"copsey" forkey:@"last_name"]; // 发送文件 [request setfile:@"/users/ben/desktop/ben.jpg" forkey:@"photo"]; // 数据的 mime 头是自动判定的,但是如果你想自定义mime头,那么这样: asiformdatarequest *request = [asiformdatarequest requestwithurl:[nsurl urlwithstring:@"http://www.dreamingwish.com"]]; // upload a file on disk [request setfile:@"/users/ben/desktop/ben.jpg" withfilename:@"myphoto.jpg" andcontenttype:@"image/jpeg" forkey:@"photo"]; // upload an nsdata instance nsdata *imagedata = uiimagepngrepresentation([uiimage imagenamed:@"myphoto.jpg"]); [request setdata:imagedata withfilename:@"myphoto.jpg" andcontenttype:@"image/jpeg" forkey:@"photo"]; // 你可以使用 addpostvalue 方法来发送相同 name 的多个数据: asiformdatarequest *request = [asiformdatarequest requestwithurl:[nsurl urlwithstring:@"http://www.dreamingwish.com"]]; [request addpostvalue:@"ben" forkey:@"names"]; [request addpostvalue:@"george" forkey:@"names"];
2、put 请求、自定义 post 请求
如果你想发送 put 请求,或者你想自定义 post 请求,使用 appendpostdata: 或者 appendpostdatafromfile:
asihttprequest *request = [asihttprequest requestwithurl:[nsurl urlwithstring:@"http://www.dreamingwish.com"]]; [request appendpostdata:[@"this is my data" datausingencoding:nsutf8stringencoding]]; // default becomes post when you use appendpostdata: / appendpostdatafromfile: / setpostbody: [request setrequestmethod:@"put"];
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: iOS使用Charts框架绘制饼状图
下一篇: 零基础学习iOS直播之采集