记录寄己走过的路

iOS 网络请求—「NSURLConnection连接」

本篇文章主要从【NSURLConnection 详解使用】学习总结。
在「时间 & 知识 」有限内,总结的文章难免有「未全、不足 」的地方,还望各位好友指出,以提高文章质量。

目录:

  1. 文件下载分类
  2. 使用步骤
  3. NSData(小文件下载)
  4. NSURLConnection使用
    1.NSURLConnection异步GET请求
    2.NSURLConnection代理GET请求
    3.NSURLConnection相关代理方法
    4.NSURLConnectionPOST请求
  5. http通信过程
  6. GET 和 POST 区别
  7. 大文件断点下载
  8. 文件上传步骤
  9. 多线程下载文件思路

1.文件下载分类

  • 按照开发中实际需求,如果按下载的 [文件大小] 划分,可以分为:小文件下载大文件下载
    因为小文件下载基本不需要等待,可以使用返回整个文件的下载方式来进行文件下载,比如说图片。
    但是大文件下载需要考虑很多情况来改善用户体验,比如说:下载进度的显示、暂停下载以及断点续传、离线断点续传,还有下载时占用手机内存情况等等。

  • 按照开发中请求方式,如果按开发 [实现方案] 划分,可以分为:NSDataNSURLConnection(iOS9.0之后舍弃)NSURLSession(推荐),以及使用第三方框架AFNetworking 方式下载文件。

2.使用步骤

NSURLConnection发送请求步骤:

  • 创建一个NSURL对象,设置请求路径
  • 传入NSURL创建一个NSURLRequest对象,设置请求头和请求体
  • 使用NSURLConnection发送请求

NSURLConnection发送请求.png

NSURLConnection发送请求方法:

1
2
3
4
5
6
7
8
9
1.同步请求
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error;
2.异步请求:根据对服务器返回数据的处理方式的不同
block回调:
+ (void)sendAsynchronousRequest:(NSURLRequest*) request queue:(NSOperationQueue*) queue                                                  completionHandler:(void (^)(NSURLResponse* response, NSData* data, NSError* connectionError)) handler;
delegate异步:
设置代理,通过代理方法

3.NSData(小文件下载)

1
2
3
4
5
NSURL *url = [NSURL URLWithString:@"[http://pic73.nipic.com/file/20150724/18576408_175304314596_2.jpg"];](http://pic73.nipic.com/file/20150724/18576408_175304314596_2.jpg%22];)
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
self.imageView.image = image;
刷新UI要放在主线程

4.NSURLConnection使用

NSURLConnection异步GET请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 1.确定请求路径
NSURL *url = [NSURL URLWithString:@"[http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];](http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON%22];)
// 2.创建请求对象
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
// 3.发送异步请求
/*
 Request:请求对象
 queue:队列(决定代码块completionHandler的在那个线程调用)
 completionHandler:当请求完成(成功|失败)的时候回调
 response:响应头
 data:响应体
 connectionError:错误信息
 */
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
    // 4.解析数据
    NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
    NSLog(@"%@",[NSThread currentThread]);
    // 转换并打印响应头信息
    NSHTTPURLResponse *r = (NSHTTPURLResponse *)response;
    NSLog(@"--%zd---%@--",r.statusCode,r.allHeaderFields);
}];
NSURLConnection代理GET请求
1
2
3
4
5
6
7
8
9
10
// 1.确定url
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_11.mp4"];
// 2.异步(自动)发送GET请求,并实现相应的代理方法
// 该方法iOS9.0之后废除了(推荐使用NSURLSession)。
NSURLConnection * connect = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:url] delegate:self];
// 设置代理方法的执行队列
// 说明:默认情况下,代理方法会在主线程中进行调用(为了方便开发者拿到数据后处理一些刷新UI的操作不需要考虑到线程间通信)
[connect setDelegateQueue:[[NSOperationQueue alloc]init]];
NSURLConnection相关代理方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#pragma mark - NSURLConnectionDataDelegate
// 1.当 接收到服务器响应 的时候调用
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{};
// 2.接收到服务器返回数据 的时候调用,调用多次(返回的NSData二进制数据(可能是片段))
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    // 拼接数据
    [self.resultData appendData:data];
}
// 3.请求完成 的时候调用(通常在该方法中解析服务器返回的数据)
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
    NSLog(@"%@",[[NSString alloc]initWithData:self.resultData encoding:NSUTF8StringEncoding]);
}
// 4.当请求失败 的时候调用
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{};
NSURLConnectionPOST请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 1.确定请求路径
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];
// 2.创建可变请求对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// 3.设置 NSMutableURLRequest 属性
// 请求方法(POST必须大写)
request.HTTPMethod = @"POST";
// 请求超时
request.timeoutInterval = 10;
// 请求头User-Agent(注意:key一定要一致(用于传递数据给后台))
[request setValue:@"ios 10.1" forHTTPHeaderField:@"User-Agent"];
// 请求体信息,字符串--->NSData
request.HTTPBody = [@"username=520it&pwd=123&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
// 4.发送请求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
     if (connectionError) {
            NSLog(@"--请求失败--");
        } else {
            // 5.解析数据
            NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
        }
}];

5.http通信过程

1
2
3
4
5
6
7
请求:请求头(NSURLRequest默认包含)+请求体(GET没有)
响应:响应头(真实类型->NSHTTPURLResponse)+响应体(要解析的数据)
GET:http://120.25.226.186:32812/login?username=123&pwd=456&type=JSON
协议+主机地址+接口名称+?+参数1&参数2&参数3
POST:http://120.25.226.186:32812/login
协议+主机地址+接口名称

6.GET 和 POST 区别

1
2
3
4
5
6
7
8
1.get请求和post请求都可以用于做获取数据请求
2.在请求数据安全方面post请求比get请求安全
1).get是以明文的方式向服务器发送请求
2).post是包装到请求体body中后,在向服务器发送请求
3).get请求的参数全部暴露在接口中,一般叫做明文请求或者傻瓜式请求,post请求的参数一般是以字典的方式进行拼接,相对于get比较安全
3.get请求的URL在使用过程中,会限制长度,因此长度非常长的请求建议用post请求
4.对文件大小的请求:get不允许向服务器上传文件(图片,pdf,音视频)
5.如果从服务器获取数据,或者查询数据,使用get请求;如果上传数据到服务器或者修改服务器上传数据使用post请求

7.大文件断点下载

1
2
3
4
1.实现思路
在下载文件的时候不再是整块的从头开始下载,而是看当前文件已经下载到哪个地方,然后从该地方接着往后面下载。
2.解决方案(通过设置请求头中的Range告诉服务器值请求一部分数据 来实现)
边下载变写入沙盒,采用追加的方式。(这里是一个线程)
8.文件上传步骤
1
2
3
4
5
6
7
8
9
10
1.确定请求路径
2.根据URL创建一个可变的请求对象
3.设置请求对象,修改请求方式为POST
4.设置请求头,告诉服务器我们将要上传文件(Content-Type)
5.设置请求体(在请求体中按照既定的格式拼接要上传的文件参数和非文件参数等数据)
1).拼接文件参数
2).拼接非文件参数
3).添加结尾标记
6.使用NSURLConnection sendAsync发送异步请求上传文件
7.解析服务器返回的数据
9.多线程下载文件思路
1
2
3
4
5
6
7
8
9
10
需求:优化下载
解决:开启多个线程下载
注意:1.目前是多个线程同时工作且异步执行的,这时就不能采用直接追加的方式了(会出现数据错乱的现象)
1.开启多条线程,每条线程都只下载文件的一部分(采用:通过设置请求头中的Range告诉服务器值请求一部分数据 来实现)
2.创建一个和需要下载文件大小一致的文件,判断当前是那个线程,根据当前的线程来判断下载的数据应该写入到文件中的哪个位置。(假设开5条线程来下载10M的文件,那么线程1下载0-2M,线程2下载2-4M一次类推,当接收到服务器返回的数据之后应该先判断当前线程是哪个线程,假如当前线程是线程2,那么在写数据的时候就从文件的2M位置开始写入)
3.代码相关:使用NSFileHandle这个类的seekToFileOfSet方法,来向文件中特定的位置写入数据。
4.技术相关
1).每个线程通过设置请求头下载文件中的某一个部分
2).通过NSFileHandle向文件中的指定位置写数据

期待


  • 如果在阅读过程中遇到 error || new ideas,希望你能 messages 我,我会及时改正谢谢。
  • 点击右上角的 喜欢 和 订阅Rss 按钮,可以收藏本仓库,并在 Demo 更新时收到邮件通知。
❄︎ 本文结束    感谢简阅 ^_^. ❄︎

本文标题:iOS 网络请求—「NSURLConnection连接」

文章作者:寄己的路

原始链接:https://sunyonghui.github.io/iOSNET/NSURLConnection.html

版权声明: 署名-非商业性使用-禁止演绎 4.0 国际 本博客所有文章除特别声明外均为原创,转载务必请「注明出处链接(可点击) - 作者」,并通过E-mail等方式告知,谢谢合作!