ios-NSURLSession

发送网络请求我们之前用的一直都是NSURLConnection,在ios7.0之后出了个NSURLSession。

用NSURLConnection发送的网络请求的过程是URL-URLRequest-URLConnection。也就是先创建个URL,然后去创建个请求,再发送请求,获取响应。

而NSURLSession就是用来代替NSURLConnection的,支持后台运行的网络任务

暂停、停止、重启网络任务,我们就可以不用自己去封装NSOperation,在NSOperation中做这个事情了。

还有就是下载、断点续传、上传、获取下载和上传的进度都是支持的。

NSURLSession可以发起DataTask、UploadTask、还有就是DownloadTask任务。这三种任务苹果都是封装好了的,这些任务默认是挂起的,我们要去开启,为什么默认是挂起了,因为NSURLSession支持暂停,暂停之后其实就是挂起状态。

NSURLSessionConfigration是配置请求的信息的.可以设置请求头,可以设置超时时长,可以设置缓存策略,可以设置是否允许蜂窝网络访问

使用如下,默认发送GET请求

- (void)dataTask {
    NSURL *url = [NSURL URLWithString:@"//"];

    
    [[[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable 
    response, NSError * _Nullable error) {
        id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
        NSLog(@"%@",json);
    }] resume];
}

发送POST请求

//发送post请求
- (void)dataTask1 {
    NSURL *url = [NSURL URLWithString:@"//"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"post";
    NSString *body = @"username=12345&password=123";
    request.HTTPBody = [body dataUsingEncoding:NSUTF8StringEncoding];
    
    
    [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * 
   _Nullable response, NSError * _Nullable error) {
        id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
        NSLog(@"%@",json);
    }] resume];
}

下载DownLoadTask的任务,内存不会暴涨,而且也是一点一点下载的

默认把文件下载到沙盒中的tmp文件夹,为什么?因为从网络上下载文件是zip文件最多,因为压缩文件可以节省用户的流量。通常情况下,下载完zip文件需要解压,所以可以解压到另一个目录,然后tmp文件夹里面的内容,系统可能在应用没运行时就删除该目录下的文件,所以此目录适合保存应用中的一些临时文件,用完就删除。

下载任务代码

- (void)downloadTask {
    NSURL *url = [NSURL URLWithString:@"//"];
    
    [[[NSURLSession sharedSession] downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * 
_Nullable response, NSError * _Nullable error) {
        //回调是在子线程上执行的
      //输出下载文件所在的文件夹
      NSLog(@"%@",location);
       //获取Document的文件路径,然后拼接一个文件
        NSString *doc = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] 
      stringByAppendingPathComponent:@"jj.cs"];
        
        //复制到其他位置,可以保存到其他的位置
        [[NSFileManager defaultManager] copyItemAtPath:location.path toPath:doc error:NULL];
        
    }] resume];

}

我们如果要跟踪下载进度的话,我们就要去使用NSURLSession的代理方法,跟踪下载进度我们不能直接使用shared,因为下载进度的获取需要用到代理,而shared不能去设置代理,我们可以去定义一个全局的属性,因为我们可能多次的去下载,然后我们给它进行懒加载,用到的时候去调用就可以了,使用NSURLSessionDownloadDelegate。我们用了代理的方法去监听下载过程的话,我们发送请求就不能用回调的方法了。因为如果我们再去写回调的话,只有回调的方法会执行,代理的方法就不会执行了什么叫调用回调的方法就是用 [[[NSURLSession sharedSession] downloadTaskWithURL:url completionHandler这个方法去请求。

#import "ViewController.h"

@interface ViewController () <NSURLSessionDownloadDelegate>
//设置全局的session
@property (nonatomic, strong) NSURLSession *session;
//生成的任务
@property (nonatomic, strong) NSURLSessionDownloadTask *downloadTask;
//保存续传的数据
@property (nonatomic, strong) NSData *resumeData;
@end

@implementation ViewController
//开始下载
- (IBAction)start:(id)sender {
    [self download];
}

//暂停下载
- (IBAction)pause:(id)sender {
    [self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
        //保存续传的数据,包含一些信息比如说已经下载的字节,下载的地址之类的
        self.resumeData = resumeData;
        
        //把续传数据保存到沙盒中,可以在退出程序的时候继续读取
        NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"kk.tmp"];
        [self.resumeData writeToFile:path atomically:YES];
        NSLog(@"%@",path);
        //设置为nil之后再点击暂停,第一行相当于给nil发消息了
        self.downloadTask = nil;
//        NSLog(@"%@",resumeData);
    }];
}
//继续下载
- (IBAction)resume:(id)sender {
    
    //从沙盒中获取续传数据
    NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"kk.tmp"];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    //判断文件是否存在
    if ([fileManager fileExistsAtPath:path]) {
        self.resumeData = [NSData dataWithContentsOfFile:path];
    }
    //判断续传数据是否存在,不存在就返回nil,防止继续多点产生的影响
    if (self.resumeData == nil) {
        return;
    }
    
    self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];
    //继续任务
    [self.downloadTask resume];
    //防止点击很多次继续按钮出现的连续下载
    self.resumeData = nil;
    
}


//懒加载
- (NSURLSession *)session {
    if (_session == nil) {
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
        //设置在主队列中执行代理方法,当delegateQueue为nil的时候效果和[NSOperation new]一样的,在子线程上执行。这里的队列也决定了回调在哪里执行
        _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    }
    return _session;
}



//开始下载
- (void)download {
    NSURL *url = [NSURL URLWithString:@"网址"];
    
    NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithURL:url];
    self.downloadTask = downloadTask;
    [downloadTask resume];

}

//代理方法
//下载完成
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
    NSLog(@"%@",[NSThread currentThread]);
    NSLog(@"下载完成:%@",location);
 //  取消操作  session一旦使用了下面这个方法之后,session无法再次使用
        [self.session invalidateAndCancel];
        //下载完成,再使session无效
        //[self.session finishTasksAndInvalidate];
        //调用为nil,就是防止我们再去做下载操作的时候程序会直接崩溃
        self.session = nil;
    
 }
//续传的方法
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes {
    NSLog(@"续传数据");
}
//获取进度的方法
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
    float process = totalBytesWritten * 1.0 /totalBytesExpectedToWrite;
    NSLog(@"下载进度: %f",process);
}
@end
如果我们在上传的文件的时候创建NSURLSession的对象用了有代理参数的方法,我们去发送请求的时候还是可以用回调的方法的,因为都会执行,只是代理中处理执行完的时候的那个方法不会执行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值