iOS 网络 NSURLSession

NSURLSession

  • 使用步骤
    • 创建NSURLSession
    • 创建Task
    • 执行Task
    • - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
      {
          [self post];
      }
      //get第一种
      - (void)get
      {
          NSLog(@"%s", __func__);
          
          NSURL *url = [NSURL URLWithString:@"http://xxxxxxxx/login?username=xxxxxxxx&pwd=xxxxxxxx&type=JSON"];
          NSURLRequest *request = [NSURLRequest requestWithURL:url];
          
          // 1.创建NSURLSession
          NSURLSession *session = [NSURLSession sharedSession];
          // 2.利用NSURLSession创建Task
          NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
              /*
               data: 服务器返回给我们的数据
               response : 响应头
               error: 错误信息
               */
              NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
          }];
          // 3.执行Task
          [task resume];
      }
      //get第二种
      - (void)get2
      {
          NSURL *url = [NSURL URLWithString:@"http://xxxxxxxx/login?username=xxxxxxxx&pwd=xxxxxxxx&type=JSON"];
          
          // 1.创建NSURLSession
          NSURLSession *session = [NSURLSession sharedSession];
          // 2.利用NSURLSession创建Task
          // 如果是通过传入url的方法创建Task, 方法内部会自动根据URL创建一个Request
          // 如果是发送Get请求, 或者不需要设置请求头信息, 那么建议使用当前方法发送请求
          NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
              NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
          }];
          // 3.执行Task
          [task resume];
      }
      //第三种使用方式 post
      - (void)post
      {
          NSURL *url = [NSURL URLWithString:@"xxxxxxxx/login"];
          NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
          request.HTTPMethod = @"POST";
          request.HTTPBody = [@"username=xxxxxxxx&pwd=xxxxxxxx&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
          
          // 1.创建NSURLSession
          NSURLSession *session = [NSURLSession sharedSession];
          // 2.利用NSURLSession创建Task
          NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
               NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
          }];
          // 3.执行Task
          [task resume];
          
      }
  • NSURLSessionDataTask

    • GET
    •    NSURL *url = [NSURL URLWithString:@"http://xxxxxxxx/login?username= xxxxxxxx&pwd= xxxxxxxx"];
          NSURLRequest *request = [NSURLRequest requestWithURL:url];
      
          // 1.获得NSURLSession对象
          NSURLSession *session = [NSURLSession sharedSession];
      
          // 2.创建任务
          NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
              NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
          }];
      
          // 3.启动任务
          [task resume];
          NSURL *url = [NSURL URLWithString:@"http://xxxxxxxx/login?username= xxxxxxxx&pwd= xxxxxxxx"];
          // 1.获得NSURLSession对象
          NSURLSession *session = [NSURLSession sharedSession];
      
          // 2.创建任务
          NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
               NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
          }];
          // 3.启动任务
          [task resume];
    • POST
    •  NSURL *url = [NSURL URLWithString:@"http://xxxxxxxx/login"];
          // 设置请求头
          NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
          request.HTTPMethod = @"POST";
          request.HTTPBody = [@"username= xxxxxxxx&pwd= xxxxxxxx" dataUsingEncoding:NSUTF8StringEncoding];
      
          // 1.获得NSURLSession对象
          NSURLSession *session = [NSURLSession sharedSession];
      
          // 2.创建任务
          NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
              NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
          }];
          // 3.启动任务
          [task resume];
    • NSURLSessionDataDelegate代理注意事项
      • Task都是通过Session监听
      • // 1.获得NSURLSession对象
        NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
      • NSURLSessionDataDelegate默认不会接受数据
      • /**
         * 1.接收到服务器的响应
         */
        - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
        {
            NSLog(@"%s", __func__);
            NSLog(@"%@", [NSThread currentThread]);
            /*
             NSURLSessionResponseAllow: 去向处理服务器响应, 内部会调用[task cancle]
             NSURLSessionResponseCancel: 允许处理服务器的响应,才会继续接收服务器返回的数据
             NSURLSessionResponseBecomeDownload: 讲解当前请求变为下载
             */
            completionHandler(NSURLSessionResponseAllow);
        }
        /**
         * 2.接收到服务器的数据(可能会被调用多次)
         */
        - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
        {
            NSLog(@"%s", __func__);
        }
        /**
         * 3.请求成功或者失败(如果失败,error有值)
         */
        - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
        {
            NSLog(@"%s", __func__);
        }
  • NSURLSessionDownloadTask

    • DownloadTask默认已经实现边下载边写入

    • // 1.创建request
        NSURL *url = [NSURL URLWithString:@"http://xxxxxxxx/resources/videos/minion_01.mp4"];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
      
        // 2.创建session
        NSURLSession *session = [NSURLSession sharedSession];
      
        // 3.创建下载任务
        NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
            NSLog(@"%@", location.absoluteString);
      
            NSFileManager *manager = [NSFileManager defaultManager];
            NSString *toPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
            toPath = [toPath stringByAppendingPathComponent:response.suggestedFilename];
            // 将下载好的文件从location移动到cache
            [manager moveItemAtURL:location toURL:[NSURL fileURLWithPath:toPath] error:nil];
        }];
      
        // 4.开启下载任务
        [task resume];
    • DownloadTask断点下载

      • 暂停: suspend
      • 继续: resume
      • 取消: cancel
      • 任务一旦被取消就无法恢复
      • 区别并返回下载信息

      • //取消并获取当前下载信息
        [self.task cancelByProducingResumeData:^(NSData *resumeData) {
          self.resumeData = resumeData;
        }];
        
        // 根据用户上次的下载信息重新创建任务
        self.task = [self.session downloadTaskWithResumeData:self.resumeData];
        [self.task resume];
    • DownloadTask监听下载进度
    • /**
       * 每当写入数据到临时文件时,就会调用一次这个方法
       * totalBytesExpectedToWrite:总大小
       * totalBytesWritten: 已经写入的大小
       * bytesWritten: 这次写入多少
       */
      - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
      {
          NSLog(@"正在下载: %.2f", 1.0 * totalBytesWritten / totalBytesExpectedToWrite);
      }
      
      /*
       * 根据resumeData恢复任务时调用
       * expectedTotalBytes:总大小
       * fileOffset: 已经写入的大小
       */
      - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
      {
          NSLog(@"didResumeAtOffset fileOffset = %lld , expectedTotalBytes = %lld", fileOffset, expectedTotalBytes);
      }
      /**
       * 下载完毕就会调用一次这个方法
       */
      - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
      {
          NSLog(@"下载完毕");
          // 文件将来存放的真实路径
          NSString *file = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
      
          // 剪切location的临时文件到真实路径
          NSFileManager *mgr = [NSFileManager defaultManager];
          [mgr moveItemAtURL:location toURL:[NSURL fileURLWithPath:file] error:nil];
      }
      /**
       * 任务完成
       */
      - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
      {
          NSLog(@"didCompleteWithError");
      }
    • 离线断点下载

      • 使用NSURLSessionDataTask
      • NSMutableURLRequest *reuqest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://xxxxxxxx/resources/videos/minion_01.mp4"]];
        // 核心方法, 实现从指定位置开始下载
        NSInteger currentBytes = KCurrentBytes;
        NSString *range = [NSString stringWithFormat:@"bytes=%zd-", currentBytes];
        [reuqest setValue:range forHTTPHeaderField:@"Range"];
        
        // 核心方法, 自己实现边下载边写入
        - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data;
  • NSURLSessionUploadTask

    • 设置设置请求头, 告诉服务器是文件上传
      • multipart/form-data; boundary=lnj
    • 必须自己严格按照格式拼接请求体
    • 请求体不能设置给request, 只能设置给fromData

      • The body stream and body data in this request object are ignored. +
      • [[self.session uploadTaskWithRequest:request fromData:body completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
          NSLog(@"%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
        }] resume];
    • 注意:以下方法用于PUT请求
    • [self.session uploadTaskWithRequest:<#(nonnull NSURLRequest *)#> fromFile:<#(nonnull NSURL *)#>]
    • 监听上传进度
    • /*
       bytesSent: 当前发送的文件大小
       totalBytesSent: 已经发送的文件总大小
       totalBytesExpectedToSend: 需要发送的文件大小
       */
      - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
      {
          NSLog(@"%zd, %zd, %zd", bytesSent, totalBytesSent, totalBytesExpectedToSend);
      }
      
      - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
      {
          NSLog(@"%s", __func__);
      }
原文地址:https://www.cnblogs.com/liujiaoxian/p/4892763.html