IOS 开发进阶--多线程和网络--NSURLSession详细解

时间:2025-03-29 08:58:50
@implementation ViewController /** NSURLSession 提供的断点续传存在的问题,不能"停",应用程序不能终止,一旦终止,续传数据就丢失了,下次还需要重头再来! */ /// 开始 - (IBAction)start { // 1. url NSURL *url = [NSURL URLWithString:@"/qqfile/QQforMac/QQ_V4.0."]; // 直接启动任务,可以通过代理跟踪进度 = [ downloadTaskWithURL:url]; // 发起下载会话 [ resume]; // 启动任务 } /// 暂停 - 下载任务 - (IBAction)pause { NSLog(@"暂停"); // 使用需要续传的数据,暂停下载任务 // 暂停方法,只需要执行一次,被暂停就不用再次暂停 // 在运行的时候,可以个 nil 发送消息,但是不会执行 /** 1. 所有的任务都是由会话发起的 2. 当任务启动后,会话会对任务进行强引用 3. 一旦任务被取消,意味着会话不再引用任务,一个 weak 对象没有其他对象强引用,会被立即释放 4. 如果属性 是 strong,除了会话之外,vc同样对任务强引用(session 为什么要使用强引用) 提问:自己开发,用 strong! */ // 这个是取消下载任务 (达到暂停的目的) [ cancelByProducingResumeData:^(NSData *resumeData) { NSLog(@"---> %tu", resumeData); // 记录续传数据 = resumeData; // 将暂停时候的数据保存起来(如果不保存下次启动的时候是没有数据的) // 释放了下载任务 = nil; // 将下地任务释放避免多次暂停的问题 }]; } /// 继续 - (IBAction)resume { // 需要避免下载任务重复创建 if ( == nil) { NSLog(@"没有续传数据"); return; } // 使用续传数据,重新实例化下载任务 // 一旦续传的下载任务被建立之后,续传数据就没有用了! = [ downloadTaskWithResumeData:]; = nil; [ resume]; } // MARK: 下载代理方法 /// 提示:如果是 iOS 7.0 开发,三个代理方法都是必须实现的 /// 下载完成 - 必须要实现的 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { NSLog(@"%@", location); } /// 断点续传的代理方法,可以什么都不写 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes { NSLog(@"%s", __FUNCTION__); } /** bytesWritten 本次下载字节数 totalBytesWritten 已经下载字节数 totalBytesExpectedToWrite 总字节数,文件大小 */ - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { // 这里设置的进度条 float progress = (float)totalBytesWritten / totalBytesExpectedToWrite; NSLog(@"%f %@", progress, [NSThread currentThread]); dispatch_async(dispatch_get_main_queue(), ^{ = progress; }); } // MARK: - 懒加载 - (NSURLSession *)session { if (_session == nil) { // 网络会话的配置 NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; /** 下载本身是异步的,并不会阻塞主线程的工作! "代理"的队列 - 只是指定了代理执行所在的队列! - [[NSOperationQueue alloc] init] * 所有的代理回调,都是异步的 - nil(效果等同于自定义队列 - 斯坦福大学白胡子老头说的使用 nil) * 所有的代理回调,都是异步的 - 主队列 * 所有的代理回调,都是在主线程异步的,不会阻塞主线程执行! * 提示:下载回调会非常频繁,如果有很多文件同时下载,同时回调,还是会影响到主线程的! * 队列的选择 - 如果完成之后,直接更新 UI,选择主队列 - 如果完成之后,要做后续的耗时(解压缩)操作,使用nil */ _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil]; } return _session; } @end