iOS-NSURLConnection使用详解

目录
  • NSURLConnection的使用步骤
  • NSURLConnection发送请求方式总结
  • NSMutableURLRequest详解
  • 断点续传实现
一 NSURLConnection的使用步骤
  • 1.创建一个NSURL对象,设置请求路径
  • 2.传入NSURL创建一个NSURLRequest对象,设置请求头和请求体
  • 3.使用NSURLConnection发送NSURLRequest
image.png
二 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);
    }];
}

打印结果

异步请求.png
  • 代理请求
// 代理
- (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);
}

打印结果

代理请求.png
二 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);
                           }];
}

运行结果

NSMutableURLRequest.png
四 断点续传下载实例

执行效果

断点下载.gif
  • 声明几个变量
// 用来写数据的文件句柄对象
@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详解(附实战代码)

你可能感兴趣的:(iOS-NSURLConnection使用详解)