iOS网络请求NSURLSession

NSURLSessioniOS7中新的网络接口。


NSURLSession提供的功能:

  1. 通过URL将数据下载到内存
  2. 通过URL将数据下载到文件系统
  3. 将数据上传到指定URL
  4. 在后台完成上述功能 


NSURLSession工作流程:

1.创建一个NSURLSessionConfiguration,用于第二步创建NSSession时设置工作模式和网络配置。

工作模式:

1.一般模式(default):这实际上与NSURLConnection的网络协议栈是一样,具有相同的共享NSHTTPCookieStorage,共享NSURLCache和共享NSURLCredentialStorage

2.及时模式(ephemeral):没有持久性存储的缓存,Cookie或证书。这对于实现像秘密浏览功能的功能来说,是很理想的。

3.后台模式(background):独特之处在于,它会创建一个后台会话。后台回话不同于常规的,普通的会话,它甚至可以在应用程序挂起,退出,崩溃的情况下运行上传和下载任务。初始化时指定的标识符,被用于向任何可能在进程外恢复后台传输的守护进程提供上下文。方法中identifier参数指定了会话的ID,用于标记后台的session


NSURLSessionConfiguration有两个属性:

      1.allowsCellularAccess属性指定是否允许使用蜂窝连接。

    2.dscretionary属性为YES时表示当程序在后台运作时由系统自己选择最佳的网络连接配置,该属性可以节省通过蜂窝连接的带宽。

    在使用后台传输数据的时候,建议使用discretionary属性,而不是allowsCellularAccess属性,因为它会把WiFi和电源可用性考虑在内。补充:这个标志允许系统为分配任务进行性能优化。这意味着只有当设备有足够电量时,设备才通过Wifi进行数据传输。如果电量低,或者只仅有一个蜂窝连接,传输任务是不会运行的。后台传输总是在discretionary模式下运行。


2.创建一个NSURLSession,系统提供了两个创建方法:

sessionWithConfiguration:  

sessionWithConfiguration:delegate:delegateQueue:


3.创建一个NSURLRequest


4.调用NSURLSession对象提供的Task函数,创建一个NSURLSessionTask

根据职能不同Task有三种子类:

1.NSURLSessionUploadTask:上传用的Task,传完以后不会再下载返回结果。

2.NSURLSessionDownloadTask:下载用的Task

3.NSURLSessionDataTask:可以上传内容,上传完后返回再进行下载。(NSURLSessionDataTask NSURLSessionDownloadTask 继承自NSURLSessionNSURLSessionUploadTask 继承自NSURLSessionDataTask


5.当不再需要连接调用SessioninvalidateAndCancel直接关闭,或者调用finishTasksAndInvalidate等待当前Task结束后关闭。这时Delegate会收到URLSession:didBecomeInvalidWithError:这个事件。Delegate收到这个事件之后会被解引用。


6.如果是一个BackgroundSession,在Task执行的时候,用户切到后台,Session会和ApplicationDelegate做交互。当程序切换到后台后,在BackgroundSession中的Task还会继续下载。






��1: 数据任务NSURLSessionDataTask: 

 // 创建请求路径

    NSString *urlStr = @"http://www.baidu.com/thcgi/get_todo_list?uid=3&oid=1";

    NSURL *url = [NSURL URLWithString:urlStr];

    

    // 创建请求

    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    

    // 创建数据任务

    NSURLSession *session = [NSURLSession sharedSession];

    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];

// 不是在主线程执行

        NSLog(@"%@", dict);

    }];

    [task resume];


��2:上传任务NSURLSessionUploadTask

// 创建请求路径

    NSString *urlStr = @"http://www.baidu.com/thcgi/get_todo_list";

    NSURL *url = [NSURL URLWithString:urlStr];

    

    // 创建请求

    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    

    // 创建参数字符串

    NSString *parmStr = @"uid=3&oid=1";

    

    // 将参数字符串转成NSData类型

    NSData *parmData = [parmStr dataUsingEncoding:NSUTF8StringEncoding];

    

    // 创建上传任务

    NSURLSession *session = [NSURLSession sharedSession];

    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:parmData completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

        // 不是在主线程执行

    }];

    [uploadTask resume];




��3:下载任务NSURLSessionDownloadTask

// 下载任务也需要一个请求,但不同之处在于它们的completionHandler。数据和上传任务在完成时立即返回,但下载任务将数据写入本地的临时文件。completionHandler有责任将文件从它的临时位置移动到一个永久位置。

 // 创建请求路径

    NSString *urlStr = @"http://p1.pichost.me/i/40/1639665.png";

    NSURL *url = [NSURL URLWithString:urlStr];

    

    // 创建请求

    NSURLRequest *request = [NSURLRequest requestWithURL:url];


    // 下载任务

    NSURLSession *session = [NSURLSession sharedSession];

    NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {

        // 不是在主线程

        // location 是一个临时位置,如果需要将下载的文件永久保存,需要将文件从它的location临时位置移动到一个永久位置。

        NSData *data = [NSData dataWithContentsOfURL:location];

        

        dispatch_async(dispatch_get_main_queue(), ^{

            UIImage *image = [UIImage imageWithData:data];

            UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectMake(10, 100, 100, 100)];

            iv.image = image;

            iv.backgroundColor = [UIColor redColor];

            [self.view addSubview:iv];

        });

    }];

    [downloadTask resume];





��4:断点续传

- (void)start:(UIButton *)btn

{

    NSLog(@"Start download task");

    // NSURLSessionNSURLRequest创建网络任务

    _task = [[self session] downloadTaskWithRequest:[self request]];

    [_task resume];

}


- (void)pause:(UIButton *)btn

{

    NSLog(@"Pause download task");

    if (_task) {

        // 取消下载任务,把已下载数据存起来

        [_task cancelByProducingResumeData:^(NSData * _Nullable resumeData) {

            _partialData = resumeData;

            _task = nil;

        }];

    }

}


- (void)stop:(UIButton *)btn

{

    NSLog(@"Stop download task");

    if (!_task) {

        // 判断是否有已下载数据,有的话就断点续传,没有就完全重新下载

        if (_partialData) {

            _task = [[self session] downloadTaskWithResumeData:_partialData];

        } else {

            _task = [[self session] downloadTaskWithRequest:[self request]];

        }

    }

    [_task resume];

}


// 创建session

- (NSURLSession *)session

{

    // 创建NSURLSession

    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];

    // delegateQueue: 决定NSURLSessionDownloadDelegate代理的方法是在哪个线程中执行

    // 如果delegateQueue设置为[NSOperationQueue mainQueue],则NSURLSessionDownloadDelegate代理的方法是在主线程中执行

    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];

    return session;

}


// 创建请求

- (NSURLRequest *)request

{

    // 创建请求

    NSURL *url = [NSURL URLWithString:@"http://p1.pichost.me/i/40/1639665.png"];

    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    return request;

}


// 创建文件本地保存目录,将文件保存在documents文件夹下

- (NSURL *)createDirectoryForDownloadItemFromURL:(NSURL *)location

{

    NSFileManager *fileManager = [NSFileManager defaultManager];

    NSArray *urls = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];

    NSURL *documentsDirectory = urls[0];

    return [documentsDirectory URLByAppendingPathComponent:[location lastPathComponent]];

}


// 把文件拷贝到指定目录

- (BOOL)copyTempFileAtURL:(NSURL *)location toDestination:(NSURL *)destination

{

    NSError *error;

    NSFileManager *fileManager = [NSFileManager defaultManager];

    [fileManager removeItemAtURL:destination error:NULL];

    [fileManager copyItemAtURL:location toURL:destination error:&error];

    

    if (error == nil) {

        return true;

    } else {

        NSLog(@"%@", error);

        return false;

    }

}


#pragma mark - NSURLSessionDownloadDelegate

// 下载完成后调用

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location

{

    // 下载成功后,文件是保存在一个临时目录的,需要开发者自己拷到放置该文件的目录

    NSLog(@"Download success for URL: %@", location.description);

    NSURL *destination = [self createDirectoryForDownloadItemFromURL:location];

    BOOL success = [self copyTempFileAtURL:location toDestination:destination];

    

    if (success) {

        // 文件保存成功后,使用GCD调用主线程把图片文件显示在UIImageView

        UIImage *image = [UIImage imageWithContentsOfFile:[destination path]];

        _imageView.image = image;

        _imageView.contentMode = UIViewContentModeScaleAspectFit;

        _imageView.hidden = NO;

    } else {

        NSLog(@"Meet error when copy file");

    }

    _task = nil;

}


// 每次接收到服务器数据时调用

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite

{

    // bytesWritten:每次下载数据的容量大小

    // totalBytesWritten:已经下载数据的容量大小

    // totalBytesExpectedToWrite:正在下载的文件总容量大小

    // 刷新进度条的delegate方法,同样地,获取数据,调用主线程刷新UI

    double currentProgress = totalBytesWritten/(double)totalBytesExpectedToWrite;

    _progressView.progress = currentProgress;

    _progressView.hidden = NO;

}


// 恢复下载时调用

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes

{

    // fileOffset:已经下载数据的容量大小

    // expectedTotalBytes:正在下载的文件总容量大小

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值