目录
- NSURLConnection的使用步骤
- NSURLConnection发送请求方式总结
- NSMutableURLRequest详解
- 断点续传实现
一 NSURLConnection的使用步骤
- 1.创建一个NSURL对象,设置请求路径
- 2.传入NSURL创建一个NSURLRequest对象,设置请求头和请求体
- 3.使用NSURLConnection发送NSURLRequest
二 NSURLConnection发送请求
- 同步请求
// macos(10.3,10.11), ios(2.0,9.0), tvos(9.0,9.0)
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request
returningResponse:(NSURLResponse **)response
error:(NSError **)error;
- 异步请求
// macos(10.7,10.11), ios(5.0,9.0), tvos(9.0,9.0)
+ (void)sendAsynchronousRequest:(NSURLRequest*) request
queue:(NSOperationQueue*) queue
completionHandler:(void (^)(NSURLResponse*response, NSData*data, NSError* connectionError));
- 代理 - 一共有3种方法
// macos(10.5,10.11), ios(2.0,9.0), tvos(9.0,9.0)
// 在startImmediately = NO的情况下,需要调用start方法开始发送请求 - start
- (instancetype)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately;
// macos(10.3,10.11), ios(2.0,9.0), tvos(9.0,9.0)
- (instancetype)initWithRequest:(NSURLRequest *)request delegate:(id)delegate;
// macos(10.3,10.11), ios(2.0,9.0), tvos(9.0,9.0)
+ (NSURLConnection*)connectionWithRequest:(NSURLRequest *)request delegate:(id)delegate;
成为NSURLConnection的代理,最好遵
NSURLConnectionDataDelegate
协议。
#pragma mark - NSURLConnectionDataDelegate
//开始接收到服务器的响应时调用
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response ;
// 接收到服务器返回的数据时调用(服务器返回的数据比较大时会调用多次)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
// 服务器返回的数据完全接收完毕后调用
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
// 请求出错时调用(比如请求超时)
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
实战代码
- 异步请求
// 异步请求
- (void)sendAsynchronousRequest {
// 1.请求路径
NSURL *url = [NSURL URLWithString:@"http://rap2api.taobao.org/app/mock/163155/gaoshilist"];
// 2.创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 3.异步发送请求
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request
queue:queue
completionHandler:^(NSURLResponse * response, NSData *data, NSError *connectionError) {
NSLog(@"length:%lu",(unsigned long)data.length);
}];
}
打印结果
- 代理请求
// 代理
- (void)sendDelegate {
// 1.请求路径
NSURL *url = [NSURL URLWithString:@"http://rap2api.taobao.org/app/mock/163155/gaoshilist"];
// 2.创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 1.创建connection
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
#pragma mark - NSURLConnectionDataDelegate
//开始接收到服务器的响应时调用
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(@"didReceiveResponse: %lld",response.expectedContentLength);
}
// 接收到服务器返回的数据时调用(服务器返回的数据比较大时会调用多次)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(@"didReceiveData: %lu",(unsigned long)data.length);
}
// 服务器返回的数据完全接收完毕后调用
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"connectionDidFinishLoading");
}
// 请求出错时调用(比如请求超时)
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(@"didFailWithError: %@",error.description);
}
打印结果
二 NSMutableURLRequest可变URL请求
NSMutableURLRequest是NSURLRequest的子类,常用方法有
// 创建请求
+ (instancetype)requestWithURL:(NSURL *)URL;
// 设置超时时长
@property NSTimeInterval timeoutInterval;
// 请求方法 GET POST
@property (copy) NSString *HTTPMethod;
// 设置请求体
@property (nullable, copy) NSData *HTTPBody;
// 设置请求头
- (void)setValue:(nullable NSString *)value forHTTPHeaderField:(NSString *)field;
三 创建GET和POST请求
- (void)mutableURLRequest {
// 1.请求路径
NSURL *url = [NSURL URLWithString:@"http://rap2api.taobao.org/app/mock/163155/login"];
// 创建请求u对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//设置请求超时等待时间(超过这个时间就算超时,请求失败)
[request setTimeoutInterval:15.0];
//设置请求方法(比如GET和POST)
[request setHTTPMethod:@"POST"];
//设置请求体
NSString *bodyStr = @"username=123&pwd=123";
[request setHTTPBody:[bodyStr dataUsingEncoding:NSUTF8StringEncoding]];
//设置请求头
[request setValue:@"" forHTTPHeaderField:@""];
// 3.异步发送请求
[NSURLConnection sendAsynchronousRequest:request
queue:[[NSOperationQueue alloc] init]
completionHandler:^(NSURLResponse * response, NSData *data, NSError *connectionError) {
NSLog(@"length:%lu",(unsigned long)data.length);
}];
}
运行结果
四 断点续传下载实例
执行效果
- 声明几个变量
// 用来写数据的文件句柄对象
@property (nonatomic, strong) NSFileHandle *writeHandle;
// 文件的总大小
@property (nonatomic, assign) long long totalLength;
// 当前已经写入的文件大小
@property (nonatomic, assign) long long currentLength;
// 连接对象
@property (nonatomic, strong) NSURLConnection *conn;
/** 进度条*/
@property(nonatomic,strong)UIView *progressView;
/** 进度值*/
@property(nonatomic,strong)UILabel *progressLbe;
- 开始下载 + 取消下载
// 开始下载
- (void)tapDownload {
if (self.conn) { // 如果有正在进行中的,需要停止先
[self tapCancel];
}
// 1.URL
NSURL *url = [NSURL URLWithString:@"http://dldir1.qq.com/qqfile/QQforMac/QQ_V5.4.0.dmg"];
// 2.请求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// 设置请求头
NSString *range = [NSString stringWithFormat:@"bytes=%lld-", self.currentLength];
[request setValue:range forHTTPHeaderField:@"Range"];
// 3.下载(创建完conn对象后,会自动发起一个异步请求)
self.conn = [NSURLConnection connectionWithRequest:request delegate:self];
}
// 取消下载
- (void)tapCancel {
[self.conn cancel];
self.conn = nil;
}
- 代理回调
#pragma mark - NSURLConnectionDataDelegate
//开始接收到服务器的响应时调用
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(@"didReceiveResponse: %lld",response.expectedContentLength);
if (self.currentLength) return; // 如果已经下载过了,就直接跳过
// 文件路径
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *filepath = [caches stringByAppendingPathComponent:@"videos.zip"];
// 创建一个空的文件 到 沙盒中
NSFileManager *mgr = [NSFileManager defaultManager];
[mgr createFileAtPath:filepath contents:nil attributes:nil];
// 创建一个用来写数据的文件句柄
self.writeHandle = [NSFileHandle fileHandleForWritingAtPath:filepath];
// 获得文件的总大小
self.totalLength = response.expectedContentLength;
}
// 接收到服务器返回的数据时调用(服务器返回的数据比较大时会调用多次)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(@"didReceiveData: %lu",(unsigned long)data.length);
// 移动到文件的最后面
[self.writeHandle seekToEndOfFile];
// 将数据写入沙盒
[self.writeHandle writeData:data];
// 累计文件的长度
self.currentLength += data.length;
float progress = (double)self.currentLength/ self.totalLength;
self.progressLbe.text = [NSString stringWithFormat:@"%.2f",progress];
CGRect frame = CGRectMake(0, 0, kScreanWidth * 0.6 * progress, 20);
self.progressView.frame = frame;
}
// 服务器返回的数据完全接收完毕后调用
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"connectionDidFinishLoading");
self.currentLength = 0;
self.totalLength = 0;
// 关闭文件
[self.writeHandle closeFile];
self.writeHandle = nil;
}
// 请求出错时调用(比如请求超时)
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(@"didFailWithError: %@",error.description);
}
五 NSURLConnection小结
5.1 下载任务方式
NSURLConnection下载文件时,先是将整个文件下载到内存,然后再写入到沙盒,如果文件比较大,就会出现内存暴涨的情况。
5.2 请求方法的控制
NSURLConnection实例化对象,实例化开始,默认请求就发送(同步发送),不需要调用start方法。而cancel可以停止请求的发送,停止后不能继续访问,需要创建新的请求。
5.3 断点续传的方式
NSURLConnection进行断点下载,通过设置访问请求的HTTPHeaderField的Range属性,开启运行循环,NSURLConnection的代理方法作为运行循环的事件源,接收到下载数据时代理方法就会持续调用,并使用NSOutputStream管道流进行数据保存。
5.4 配置信息
NSURLConnection不能进行这个配置,相比较与NSURLConnection依赖与一个全局的配置对象,缺乏灵活性而言。
本文参考
iOS开发 - NSURLConnection实现断点续传下载
项目连接地址 - NSURLConnectionDemo
更多相关文章参考
iOS-NSURLSession与NSURLConnection区别
iOS-NSURLSession详解(附实战代码)