欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

分析一下iOS网络请求的使用

程序员文章站 2022-05-01 17:38:31
前言:苹果官方提供的网络请求api有两种: nsurlconnection、nsurlsession。 还有,目前的用的最多是主流框架:afnetworking ios 7之前,只有 nsurlco...

前言:苹果官方提供的网络请求api有两种: nsurlconnection、nsurlsession。

还有,目前的用的最多是主流框架:afnetworking

ios 7之前,只有 nsurlconncetion

ios 9之后,苹果官方放弃nsurlconnection,推荐使用nsurlsession

本文将介绍ios原生api和afn的使用。


苹果官方api:

以下将分别讲述这两种请求的简单使用:

nsurlconnection:

-(void)demo1{
 //访问百度首页
 
 //1. 创建一个网络请求
 nsurl *url = [nsurl urlwithstring:@"https://m.baidu.com"];
 
 nsurlrequest *request = [nsurlrequest requestwithurl:url];
 
 //2. 发送网络请求  网络请求是个耗时操作,在子线程发送
 
 //第一种发送网络请求的方式
 
 /*
  * 利用 nsurlconnection 发送一个异步的网络请求
  *
  * @param nsurlrequest 网络请求
  *
  * @return
  */
 //queue:操作队列,决定网络请求完成后的block(completionhandler) 回调在那条线程执行
 //[nsoperationqueue mainqueue] 主线程
 //completionhandler :block 回调:网络请求完成之后,就会自动调用这个 block
 [nsurlconnection sendasynchronousrequest:request queue:[nsoperationqueue mainqueue] completionhandler:^(nsurlresponse * _nullable response, nsdata * _nullable data, nserror * _nullable connectionerror) {
  //response : 响应:服务器的响应
  //data:二进制数据:服务器返回的数据。(就是我们想要的内容)
  //coonectionerror:链接错误的信息
  nslog(@"网络响应:response:%@",response);
  
  //根据返回的二进制数据,生成字符串!nsutf8stringencoding:编码方式
  nsstring *html = [[nsstring alloc]initwithdata:data encoding:nsutf8stringencoding];
  
  //在客户端直接打开一个网页!
  //客户端服务器:uiwebview
  
  //实例化一个客户端浏览器
  uiwebview *web = [[uiwebview alloc]initwithframe:self.view.bounds];
  
  //加载html字符串:baseurl:基准的地址:相对路径/绝对路径
  [web loadhtmlstring:html baseurl:nil];
  
  //将浏览器加载到view上
  [self.view addsubview:web];
  
//  //在本地保存百度首页
//  [data writetofile:@"/users/liu/desktop/baidu.html" atomically:yes];
  
  nslog(@"网路链接错误 connectionerror响应:response:%@",connectionerror);
 }];
}
nsurlsession:
//nsurlsession
-(void)demo2{
 //访问百度首页
 
 //1. 创建一个网络请求
 nsurl *url = [nsurl urlwithstring:@"https://m.baidu.com"];
 
 //2.创建请求对象
 nsurlrequest *request = [nsurlrequest requestwithurl:url];
 
 //3.获得会话对象
 nsurlsession *session=[nsurlsession sharedsession];
 
 //4.根据会话对象创建一个task(发送请求)
 /*
  第一个参数:请求对象
  第二个参数:completionhandler回调(请求完成【成功|失败】的回调)
  data:响应体信息(期望的数据)
  response:响应头信息,主要是对服务器端的描述
  error:错误信息,如果请求失败,则error有值
  */
 nsurlsessiondatatask *datatask=[session datataskwithrequest:request completionhandler:^(nsdata * _nullable data, nsurlresponse * _nullable response, nserror * _nullable error) {
//response : 响应:服务器的响应
//data:二进制数据:服务器返回的数据。(就是我们想要的内容)
//error:链接错误的信息
nslog(@"网络响应:response:%@",response);
  
//根据返回的二进制数据,生成字符串!nsutf8stringencoding:编码方式
nsstring *html = [[nsstring alloc]initwithdata:data encoding:nsutf8stringencoding];

//在客户端直接打开一个网页!
//客户端服务器:uiwebview

//将浏览器加载到view上
dispatch_async(dispatch_get_main_queue(), ^{

//实例化一个客户端浏览器
uiwebview *web = [[uiwebview alloc]initwithframe:self.view.bounds];

//加载html字符串:baseurl:基准的地址:相对路径/绝对路径
[web loadhtmlstring:html baseurl:nil];
[self.view addsubview:web];

});
  
//  //在本地保存百度首页
//  [data writetofile:@"/users/liu/desktop/baidu.html" atomically:yes];
  
  }
 ];
 
 //5.执行任务
 [datatask resume];
}

使用nsurlsession发送get请求的方法和nsurlconnection类似,整个过程如下:

1)确定请求路径(一般由公司的后台开发人员以接口文档的方式提供),get请求参数直接跟在url后面

2)创建请求对象(默认包含了请求头和请求方法【get】),此步骤可以省略

3)创建会话对象(nsurlsession)

4)根据会话对象创建请求任务(nsurlsessiondatatask)

5)执行task

6)当得到服务器返回的响应后,解析数据(xml|json|http)

使用nsurlsession发送post请求的方法和nsurlconnection类似,整个过程如下:

1)确定请求路径(一般由公司的后台开发人员以接口文档的方式提供)

2)创建可变的请求对象(因为需要修改),此步骤不可以省略

3)修改请求方法为post

4)设置请求体,把参数转换为二进制数据并设置请求体

5)创建会话对象(nsurlsession)

6)根据会话对象创建请求任务(nsurlsessiondatatask)

7)执行task

8)当得到服务器返回的响应后,解析数据(xml|json|http)

//post方法
//1.创建会话对象
 nsurlsession *session=[nsurlsession sharedsession];

 //2.根据会话对象创建task
 nsurl *url=[nsurl urlwithstring:@"https://123.207.175.144/test1.php"];

 //3.创建可变的请求对象
 nsmutableurlrequest *request=[nsmutableurlrequest requestwithurl:url];

 //4.修改请求方法为post
 request.httpmethod=@"post";

 //5.设置请求体
 request.httpbody=[@"login=1" datausingencoding:nsutf8stringencoding];

 //6.根据会话对象创建一个task(发送请求)
/*
第一个参数:请求对象
第二个参数:completionhandler回调(请求完成【成功|失败】的回调)
  data:响应体信息(期望的数据)
  response:响应头信息,主要是对服务器端的描述
  error:错误信息,如果请求失败,则error有值
 */
  nsurlsessiondatatask *datatask = [session datataskwithrequest:request completionhandler:^(nsdata * _nullable data, nsurlresponse * _nullable response, nserror * _nullable error){

  //8.解析数据
  nsdictionary *dict=[nsjsonserialization jsonobjectwithdata:data options:kniloptions error:nil];
  nslog(@"%@",dict);
 }];

  //7.执行任务
 [datatask resume];

有的时候,我们可能需要监听网络请求的过程(如下载文件需监听文件下载进度),那么就需要用到代理方法。

//代理方法
#import "viewcontroller.h"

@interface viewcontroller ()
@property (nonatomic, strong) nsmutabledata *responsedata;
@end

@implementation viewcontroller

-(nsmutabledata *)responsedata
 {
if (_responsedata == nil) {
  _responsedata = [nsmutabledata data];
 }
return _responsedata;
}

- (void)viewdidload {
 [super viewdidload];
 // do any additional setup after loading the view, typically from a nib.
  //[self performselector:@selector(getandsynchronousmethod)];
 [self delegatetest];
}

-(void)delegatetest
{
//1.确定请求路径
nsurl *url = [nsurl urlwithstring:@"https://123.207.175.144/test1.php?login=1"];

//2.创建请求对象
//请求对象内部默认已经包含了请求头和请求方法(get)
nsurlrequest *request = [nsurlrequest requestwithurl:url];

//3.获得会话对象,并设置代理
/*
第一个参数:会话对象的配置信息defaultsessionconfiguration 表示默认配置
第二个参数:谁成为代理,此处为控制器本身即self
第三个参数:队列,该队列决定代理方法在哪个线程中调用,可以传主队列|非主队列
[nsoperationqueue mainqueue]主队列:代理方法在主线程中调用
[[nsoperationqueue alloc]init] 非主队列: 代理方法在子线程中调用
*/
nsurlsession *session = [nsurlsession sessionwithconfiguration:[nsurlsessionconfiguration defaultsessionconfiguration] delegate:self delegatequeue:[nsoperationqueue mainqueue]];

//4.根据会话对象创建一个task(发送请求)
nsurlsessiondatatask *datatask = [session datataskwithrequest:request];

//5.执行任务
[datatask resume];

}

//1.接收到服务器响应的时候调用该方法
 -(void)urlsession:(nsurlsession *)session datatask:(nsurlsessiondatatask *)datatask didreceiveresponse:(nsurlresponse *)response completionhandler:(void (^)(nsurlsessionresponsedisposition))completionhandler
 {
//在该方法中可以得到响应头信息,即response
nslog(@"didreceiveresponse--%@",[nsthread currentthread]);

//注意:需要使用completionhandler回调告诉系统应该如何处理服务器返回的数据
//默认是取消的
/*
nsurlsessionresponsecancel = 0,  默认的处理方式,取消
nsurlsessionresponseallow = 1,接收服务器返回的数据
nsurlsessionresponsebecomedownload = 2,变成一个下载请求
nsurlsessionresponsebecomestream  变成一个流
*/

completionhandler(nsurlsessionresponseallow);
}

//2.接收到服务器返回数据的时候会调用该方法,如果数据较大那么该方法可能会调用多次
 -(void)urlsession:(nsurlsession *)session datatask:(nsurlsessiondatatask *)datatask didreceivedata:(nsdata *)data
 {
nslog(@"didreceivedata--%@",[nsthread currentthread]);

//拼接服务器返回的数据
[self.responsedata appenddata:data];
}

//3.当请求完成(成功|失败)的时候会调用该方法,如果请求失败,则error有值
 -(void)urlsession:(nsurlsession *)session task:(nsurlsessiontask *)task didcompletewitherror:(nserror *)error
 {
nslog(@"didcompletewitherror--%@",[nsthread currentthread]);

if(error == nil)
 {
//解析数据
nsdictionary *dict = [nsjsonserialization jsonobjectwithdata:self.responsedata options:kniloptions error:nil];
nslog(@"%@",dict);
  }
}

@end

如果返回的字符有汉字,可以为nsdictionary提供一个分类,重写系统中的方法。

//重写dictionary
#import "nsdictionary+log.h"

@implementation nsdictionary (log)
-(nsstring *)descriptionwithlocale:(id)locale indent:(nsuinteger)level
 {
//初始化可变字符串
nsmutablestring *string = [nsmutablestring string];
//拼接开头[
[string appendstring:@"["];

//拼接字典中所有的键值对
[self enumeratekeysandobjectsusingblock:^(id  _nonnull key, id  _nonnull obj, bool * _nonnull stop) {
  [string appendformat:@"%@:",key];
  [string appendformat:@"%@",obj];
 }];

//拼接结尾]
[string appendstring:@"]"];

return string;
}

@end

afnetworking:

afnetworking开源库封装了原生的方法,
ios9.0之后,
由于nsurlconnection的弃用,
afnetworking的使用也有一些改变。

注:使用前需要导入afn框架:afn框架地址

get请求:
//get请求
-(void)demo1{
 nsstring *urlstring = @"https://www.liubaiqi.cn";
 
 afhttpsessionmanager *manger =[afhttpsessionmanager manager];
 
 [manger get:urlstring parameters:nil progress:^(nsprogress * _nonnull downloadprogress) {
  
 } success:^(nsurlsessiondatatask * _nonnull task, id  _nullable responseobject) {
  nslog(@"成功");
 } failure:^(nsurlsessiondatatask * _nullable task, nserror * _nonnull error) {
  nslog(@"%@",error);
 }];
}
post请求:
//post请求
-(void)demo2{
 nsstring *urlstring = @"https://192.168.1.101:8080";
 
 afhttpsessionmanager *manger =[afhttpsessionmanager manager];
 
 nsmutabledictionary *parameter= @{@"":@"",@"":@""};
 
 [manger post:urlstring parameters:parameter progress:^(nsprogress * _nonnulluploadprogress){
  
 }success:^(nsurlsessiondatatask * _nonnull task, id  _nullable responseobject) {
  nslog(@"成功");
 } failure:^(nsurlsessiondatatask * _nullable task, nserror * _nonnull error) {
  nslog(@"%@",error);
 }];
}
download请求:
//download请求
-(void)demo3{
 //1. 创建nsurlsessionconfiguration
 nsurlsessionconfiguration *configuration = [nsurlsessionconfiguration defaultsessionconfiguration];
 
 //2. 创建管理者对象
 afurlsessionmanager *manager = [[afurlsessionmanager alloc]initwithsessionconfiguration:configuration];
 
 //3. 设置url
 nsurl *url = [nsurl urlwithstring:@"https://127.0.0.1/1.mp4"];
 
 //4. 创建请求对象
 nsurlrequest *request = [nsurlrequest requestwithurl:url];
 
 //5. 下载任务
 nsurlsessiondownloadtask *downloadtask = [manager downloadtaskwithrequest:request progress:^(nsprogress * _nonnull downloadprogress) {
  //打印下载进度
  nslog(@"%lf",1.0*downloadprogress.completedunitcount/downloadprogress.totalunitcount);
  
 } destination:^nsurl * _nonnull(nsurl * _nonnull targetpath, nsurlresponse * _nonnull response) {
  //设置下载路径
  nsurl *documentsdirectoryurl = [[nsfilemanager defaultmanager]urlfordirectory:nsdocumentdirectory indomain:nsuserdomainmask appropriateforurl:nil create:no error:nil];
  
  return [documentsdirectoryurl urlbyappendingpathcomponent:[response suggestedfilename]];
  
 } completionhandler:^(nsurlresponse * _nonnull response, nsurl * _nullable filepath, nserror * _nullable error) {
  //下载完成
  nslog(@"file downloaded to : %@",filepath);
 }];
 //启动任务
 [downloadtask resume];
}
upload请求:
//upload请求
-(void)demo4{
 //创建nsurlsessionconfiguration
 nsurlsessionconfiguration *configuration = [nsurlsessionconfiguration defaultsessionconfiguration];
 
 //创建管理者对象
 afurlsessionmanager *manager = [[afurlsessionmanager alloc]initwithsessionconfiguration:configuration];
 
 //设置url
 nsurl *url = [nsurl urlwithstring:@"https://127.0.0.1"];
 //创建请求对象
 nsurlrequest *request = [nsurlrequest requestwithurl:url];
 //文件路径
 nsurl *filepath = [nsurl fileurlwithpath:@"file://users/liu/desktop/note"];
 
 //上传任务
 nsurlsessionuploadtask *uploadtask = [manager uploadtaskwithrequest:request fromfile:filepath progress:nil completionhandler:^(nsurlresponse * _nonnull response, id  _nullable responseobject, nserror * _nullable error) {
  if(error){
//错误
nslog(@"error:%@",error);
  }else{
//成功
nslog(@"success %@ %@",response,responseobject);
  }
 }];
 //启动任务
 [uploadtask resume];
}

网络状态:

//网络状态
-(void)demo5{
 //1. 创建网络监测者
 afnetworkreachabilitymanager *manager = [afnetworkreachabilitymanager sharedmanager];
 
 [manager setreachabilitystatuschangeblock:^(afnetworkreachabilitystatus status) {
  //监测网络改变
  switch (status) {
case afnetworkreachabilitystatusunknown:
 nslog(@"未知网络状态");
 break;
case afnetworkreachabilitystatusnotreachable:
 nslog(@"无网络");
 break;
case afnetworkreachabilitystatusreachableviawwan:
 nslog(@"蜂窝数据网络");
 break;
case afnetworkreachabilitystatusreachableviawifi:
 nslog(@"wifi网络");
 break;
 
default:
 break;
  }
 }];
}

本文参考了组长的blog,以及自己学习时整理的一些小demo。