当用户关闭应用程序并且任务仍处于活动状态时,NSURLSessionDownloadTask 不会删除文件
Posted
技术标签:
【中文标题】当用户关闭应用程序并且任务仍处于活动状态时,NSURLSessionDownloadTask 不会删除文件【英文标题】:NSURLSessionDownloadTask not deleting the file when the app is closed by the user and the task was still active 【发布时间】:2015-07-28 16:49:29 【问题描述】:我有一个NSURLSession
和一个NSURLSessionDownloadTask
配置为在后台下载文件,如果用户取消下载任务,所有数据都被删除并且文件正在使用的存储空间被释放,但如果应用程序从多任务坞站关闭,下载任务终止并给出错误,但没有删除数据,文件的临时数据仍在占用存储空间并且永远不会被释放。我需要做什么才能释放空间?
这是我的NSURLSession
配置和错误处理:
- (NSURLSession *)backgroundSession
static NSURLSession *session = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
NSURLSessionConfiguration *configuration;
if ([[UIDevice currentDevice].systemVersion hasPrefix:@"7"]) configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.visyon.pr"];
else configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.visyon.pr"];
configuration.sessionSendsLaunchEvents =YES;
session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
);
return session;
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
if (error == nil)
NSLog(@"Task: %@ completed successfully", task );
else
// [self hideActivity];
// [self showAlertBoxErrorDownload];
NSLog(@"Task: %@ completed with error: %@, %lu", task, [error localizedDescription], (long)error.code);
self.downloadTask = nil;
【问题讨论】:
用户取消下载时,你如何删除数据? 嗨,MikeAtNobel,它会被自动删除,我不需要做任何事情。当用户触摸按钮取消时,我调用[NSURLSessionDownloadTask cancel]
应用强制退出时是否调用?
否未取消,这是关闭应用程序之前的任务下载 ID:<__NSCFBackgroundDownloadTask: 0x146d2f990> taskIdentifier: 2
然后我在任务仍在下载时关闭应用程序,当我再次打开应用程序时出现下一个错误:Task: <__NSCFBackgroundDownloadTask: 0x135e24460> taskIdentifier: 3 completed with error: unsupported URL, 18446744073709550614
无法调用“[NSURLSessionDownloadTask cancel]”,因为该应用程序处于后台并且离多任务处理坞很近。
【参考方案1】:
好的,经过10多天的尝试和失败,我找到了解决方案,首先有两种情况,用户关闭应用,后台有活动下载,请注意这种情况下载任务永远不会被恢复。
场景 1. 当用户关闭应用但仍处于活动状态时,- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
被调用,用于下载的临时文件直接进入应用的临时目录,在本例中为 - (void)applicationWillTerminate:(UIApplication *)application
被调用,但下载任务的委托首先被调用。解决方案是这种情况下是实现代码每次打开app时清理临时目录或者让ios清理临时文件夹,这里解释一下iOS什么时候清理临时文件:
When does iOS clean the local app ./tmp directories?
场景 2. 当用户在后台模式下关闭应用程序时,应用程序被终止,下次打开应用程序时,- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
被调用,用于下载的临时文件存储在 NSCachesDirectory
在下一个目录中:
var/mobile/Containers/Data/Application/CA21-B6E8-3305A39/Library/Caches/com.apple.nsurlsessiond/Downloads/com.xxx.xxx/CFNetworkDownload_M5o8Su.tmp
下次有新下载时,临时文件将移动到应用程序的临时目录。
这里的解决方案是在- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
启动后立即执行代码以从Caches/com.apple.nsurlsessiond/Downloads/com.xxx.xxx/
中删除所有临时文件。
这是从NSCachesDirectory
删除临时文件的代码:
NSString *path = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSArray *array = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[path stringByAppendingPathComponent:@"/com.apple.nsurlsessiond/Downloads/com.xxx.xxx/"] error:nil];
for (NSString *string in array)
[[NSFileManager defaultManager] removeItemAtPath:[path stringByAppendingPathComponent:[NSString stringWithFormat:@"/com.apple.nsurlsessiond/Downloads/com.xxx.xxx/%@", string]] error:nil];
但是因为它只适用于这种情况,所以最好在每次启动时实现代码来清理应用程序的临时目录,或者让 iOS 清理临时文件夹,这样它就适用于这两种情况。
下面是如何清理应用临时目录的代码:
NSString *path = NSTemporaryDirectory();
NSArray *array = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil];
for (NSString *string in array)
[[NSFileManager defaultManager] removeItemAtPath:[path stringByAppendingPathComponent:string] error:nil];
【讨论】:
终于找到了解决方案。谢谢@user1241006。我的 iOS 应用程序出现了一些问题。 :) @ajeet sharma 欢迎,请不要忘记为帖子投票【参考方案2】:第一点是如果您使用后台配置类型配置 nsurlsession。如果用户杀死应用程序,那么这种类型的会话直到运行。 第二点,如果要清除空间,则需要停止该会话并手动编写代码以从 tmp 文件夹中删除临时文件。
更改会话配置类型。
【讨论】:
这是 borderline 一个可以接受的答案。您是否有机会为您在回答中提出的一些观点添加更多细节?如何停止会话?您有删除临时文件的手动代码示例吗?会话配置类型应该更改为什么,为什么?【参考方案3】:AppDelegate 中有一个名为- (void)applicationWillTerminate:(UIApplication *)application
的方法。您可以尝试从那里拨打[NSURLSessionDownloadTask cancel];
;或者尝试设置一个标志,以在应用关闭时向应用指示正在下载,并在下次打开应用时删除数据。
【讨论】:
- (void)applicationWillTerminate:(UIApplication *)application
在您从多任务处理坞关闭应用程序时没有接到电话。
对不起,我应该抓到那个的。由于应用程序在关闭时处于后台,因此不会调用该方法。查看 Apple 的文档 (developer.apple.com/library/ios/documentation/iPhone/Conceptual/…) 似乎表明在这种状态下可能没有处理数据的标准方法。您可能需要找出一种自定义方法来确定下载位置中的数据是否良好。以上是关于当用户关闭应用程序并且任务仍处于活动状态时,NSURLSessionDownloadTask 不会删除文件的主要内容,如果未能解决你的问题,请参考以下文章