美文网首页网络请求
iOS-NSURLConnection使用详解

iOS-NSURLConnection使用详解

作者: 路飞_Luck | 来源:发表于2019-04-02 23:44 被阅读0次
    目录
    • 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使用详解

        本文链接:https://www.haomeiwen.com/subject/vggnbqtx.html