iOS开发之断点下载时session造成的内存泄漏
然后是相应的注意点 以及一个 断点下载的小例子
- 注意点
- > 1. 在下载完成之后需要对URLSession 做finishTasksAndInvalidate操作;
- > 或者进行invalidateAndCancel 操作也行
- > 2. 下载的文件保存再temp问价夹中下载完成后会自动删除,需要再下载完成的时候自行进行处理
- > 3. 一旦对session发送了invalidateAndCancel消息,session就再也无法发起任务了!
- > 4. 在处理临时文件的时候调用[[NSFileManager defaultManager] copyItemAtPath:tempPath toPath:cachePath error:NULL]; 可以解决内存飙升问题
- >5.
- #import "ViewController.h"
- @interface ViewController () <NSURLSessionDownloadDelegate >
- @property (nonatomic, strong) NSURLSession *session;
- @end
- @implementation ViewController
- /**
- 重要
- session对象,会对代理进行强引用,如果不调用invalidateAndCancel取消 session,会出现内存泄漏
- 官方文档中的说名
- The session object keeps a strong reference to the delegate until your app explicitly invalidates the session. If you do not invalidate the session by calling the invalidateAndCancel or resetWithCompletionHandler: method, your app leaks memory.
- */
- - (NSURLSession *)session {
- if (_session == nil) {
- // session 是为了方便程序员使用的全局的单例,如果要通过代理跟进下载进度,需要自己实例化一个session
- // NSURLSession *session = [NSURLSession sharedSession];
- // config可以配置session,指定session中的超时时长,缓存策略,安全凭据,cookie...
- // 可以保证全局共享,统一在一个网络会话中使用!
- NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
- /**
- 队列:如果指定nil,会默认使用异步执行队列的代理方法
- 因为:所有网络操作默认都是异步的,因此不指定队列,就是异步的
- */
- // NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
- _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
- }
- return _session;
- }
- - (void)dealloc {
- [self.session invalidateAndCancel];
- NSLog(@"我去了");
- }
- /**
- 跟踪下载进度
- */
- - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
- // url
- NSString *urlString = @"http://127.0.0.1/01.C语言-语法预览.mp4";
- urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
- NSURL *url = [NSURL URLWithString:urlString];
- // 数据任务
- // 如果要跟踪下载进度,在session中,同样是需要代理
- [[self.session downloadTaskWithURL:url] resume];
- }
- #pragma mark - 下载的代理方法
- /** 下载完成 */
- - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
- didFinishDownloadingToURL:(NSURL *)location {
- NSLog(@"+++%@", location);
- /***********************************************/
- // 完成任务 完成的时候需要进行释放否则会造成内存泄露
- [self.session finishTasksAndInvalidate];
- }
- // 以下两个方法,在iOS7中,是必须的
- // ios8中变成了可选的
- /**
- 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]);
- }
- // 断点续传的
- - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
- didResumeAtOffset:(int64_t)fileOffset
- expectedTotalBytes:(int64_t)expectedTotalBytes {
- // 通常不用写任何东西
- }
- @end