服务器上很多iOS临时文件,ios – NSURLSessionDownloadTask移动临时文件

讨论的后期,但我已经看到了相同/类似的问题并进行了调查.

通过我的调查,你所看到的是预期的(我应该说“它被观察到了吗?”).

但由于我不是100%确定你是如何使用URL会话的,所以我将其放在我想要做的之下,然后是我的观察(仅限重要的).

另外,我创建了一个sample project并将其作为downLoader.zip放入here.您可以播放并检查URL会话后台下载的工作方式.但是在试玩之前最好通过下面的内容阅读,尽管这是一个相当长的注意事项.

答:我正在努力做什么

我正在开发一种地图应用程序,我需要一次下载1000个小尺寸(0.5-150kB,大多数~20kB)的PNG文件.它们的总下载大小约为50MB,下载所有这些内容需要几分钟.我认为将用户留在我的应用程序只是等待下载是糟糕的设计,所以我让应用程序使用URL Session的后台下载.

但是,我必须承认,Apple’s doc表示“后台会话已经过优化,可以传输少量可以根据需要恢复的大型资源.”因此,我使用后台会话的方式完全相反.但无论如何…

B.我所观察到的

下面,我列出了我的观察和我对原因的猜测.我应该说猜测,因为他们没有记录.

(1)观察:有时,应该带有didFinishDownlaoding的文件不存在.

临时文件放在:

/var/mobile/Containers/Data/Application/randomHexString/Library/Caches/com.apple.nsurlsessiond/Downloads/yourName.yourApp. randomHexString从应用程序的运行更改为运行.当文件不存在时,didFinishDownloadingTo附带的randomHexString是“previous”会话中的randomHexString.现在,“previous”在这里意味着应用程序之前运行的会话!在当前运行的当前会话中显然不存在.

对于不存在的文件还有另一种情况,即randomHexString没问题,但文件不存在.这似乎发生在请求会话取消(invalidateAndCancel)之后和会话变为无效之前(didBecomeInvalidWithError).

猜测:这种情况尤其发生在开发阶段,因为我们在下载时手动或通过调试器或仅通过bug来终止应用程序.一旦下载请求被移交并被操作系统接受,操作系统即使在应用程序退出后也会处理我们的请求.请注意,我们无法知道操作系统是否已明确接受了请求.即使从URLSessionDownloadTask:resume()返回后,有时文件也不会在下次启动时退出,有时它们会退出.

解决方法:如果文件不存在,请忽略它们.有一段时间,“这个时间”的文件应该来了.

(2)观察:有时,重复(相同)文件带有didFinishDownloadingTo.

我的应用将下载的PNG文件转换为其他格式. W / in didFinishDownlaodingTo,我将临时文件(== OS指定)移动到我的应用程序的另一个目录,然后生成线程(GCD)以转换格式并删除下载的临时文件.因此,要覆盖的另一个线程(didFinishDownlaodingTo)是一个问题.

解决方法:我列出了URLSessionTask:taskIdentifier和w / in didFinishDownlaodingTo,通过检索taskID列表来检查重复,以忽略重复的文件.

(3)观察:即使用户终止了应用程序,操作系统也会重新启动应用程序.

在用户从任务切换器终止应用程序之后,操作系统会重新启动应用程序w / application:handleEventsForBackgroundURLSession:completionHandler.

请注意,重新启动的顺序是didFinishLaunchingWithOptions首先作为常规启动,然后是handleEventsForBackgroundURLSession.

从用户的POV,当他/她终止应用程序时,就是这样,完成了!它甚至在终止应用程序后看起来很奇怪,它会重新启动并向他们通知某些内容.它就像一个僵尸.

猜猜:Apple’s document说“如果用户终止你的应用程序,系统会取消任何待处理的任务”. “待定任务”的定义没有明确说明,但据我所知,这是来自iOS POV而非用户或程序开发人员.正如在(1)中猜测的那样,iOS似乎已经接受了下载请求,并且它们不再是“待定任务”.

解决方法:在将所有下载请求传递给iOS后,我创建了一个“flagFile”w / URLSessionDownloadTask:resume(),其中的文件意味着“正在下载”.当用户终止应用程序时,在UIApplicationDelegate:applicationWillTerminate,我删除了标志文件.或者,如果所有下载请求都未传递给iOS,则没有标记文件.然后在应用程序重新启动UIApplicationDelegate:handleEventsForBackgroundURLSession,我检查是否有标志文件.如果遗漏,那么我可以假设用户终止了.这里有两个选择.选择1:我不会重新创建URL会话.接下来会发生什么,iOS将在大约20秒后终止我的应用程序.我不知道这是否(==没有创建URL会话)是合法的操作,但它的工作原理.用户可以在这20秒内启动,所以我添加了一些代码来处理这种情况.选择2:我创建了URL会话.接下来发生的事情是iOS调用委托方法didFinishDownlaodingTo / didCompleteWithError,然后是urlSessionDidFinishEvents.如果我在这里没有做任何事情,那么进程(app)会无限期地保持活动而不会向用户发送任何通知:任务切换器中没有任何内容.这只不过是浪费记忆.这里的选项是触发本地通知,让用户知道我的应用程序,以便他们可以返回我的应用程序并终止(再次!),虽然我的应用程序显然是一个僵尸.两个选项都有一个问题:在某些情况下可能不会调用applicationWillTerminate(尽管我已经确认).在这种情况下,标记文件将保留为常规操作并向用户显示僵尸.所以,标志文件方法只是缓解了这个问题,但我认为它适用于我的应用程序大部分时间.

请注意,当应用程序被xcode调试程序杀死或被OS w / bug(SEGFALUT)杀死时,应用程序会重新启动.

(4)观察:应用程序终止后(由用户等)然后由OS重新启动,应用程序偶尔处于活动状态(UIApplication.shared.applicationState为.active).

我想通过本地通知通知用户下载完成,但由于它处于活动状态,因此本地通知不会触发.所以,我需要使用UIAlertController.因此,我无法提供一致的用户体验,而且对于用户来说应该看起来很奇怪:大多数时候本地通知而且非常偶尔会有UIAlert.请注意,当应用程序以活动状态启动时,它将显示在任务切换器中.

猜猜:完全不知道这是怎么发生的.一个好的(?)事情只是偶尔发生.

解决方法:似乎没有.

(5)观察:handleEventsForBackgroundURLSession / urlSessionDidFinishEvents只调用一次.

我在启动后台任务(application.beginBackgroundTask)后开始下载.然后在beginBackgroundTask的expiration处理程序中,我调用endBackgroundTask.我不确切知道为什么,但在endBackgroundTask之后,我的进程仍然有很多处理时间,所以我可以继续请求下载.这可能是因为下载文件继续w / didFinishDownlaodingTo.为了成为一个好公民,我暂停请求进一步下载,并向用户发送本地通知以将应用程序置于前台.现在,一旦我暂停请求,在4-5秒内,OS确定URL会话结束并且handleEventsForBackgroundURLSession然后调用urlSessionDidFinishEvents.这是一次性活动.当用户将应用程序置于前台以恢复下载,然后再将其放入后台时,将不再出现handleEventsForBackgroundURLSession / urlSessionDidFinishEvents.我不清楚会话的开始和结束的定义.似乎会话在第一个URLSessionTask.resume()开始,然后结束w / timeout,这似乎是由URLSessionConfiguration.timeoutIntervalForRequest确定的.但是,在这里设置大数(1000秒)不会影响任何事情,它总是4-5秒.

猜猜:不知道

解决方法:在应用程序处于活动状态时,不要在urlSessionDidFinishEvents上进行中继.仅当应用程序重新启动操作系统和初始handleEventsForBackgroundURLSession / urlSessionDidFinishEvents时才重新启动.

===============

下面,我列出了sample project(downLoader.zip).您可以使用样本验证以上所有内容.

>该应用程序有一个下载文件列表.文件数量为1921,总共56MB.它们是256×256 PNG地图图块文件,位于由Geo Spatial Information Authority of Japan(GSI)管理的服务器中.下载后,它们将被移至Library / Cache / download.如果您的设备被越狱,您可以使用Filza查看它们.

>崩溃自己测试重新启动

>模拟后台任务到期

>由于OS重新启动后调试器不起作用,因此记录到文件.该文件在Documents中,可以移动到PC.

>玩真实的设备.模拟器不会重新启动应用程序.

>使用Xcode 8.3.3构建的项目,并使用iphone6 /9.3.3和iphone7 /10.3.1进行测试

>要查看应用程序是否重新启动w / xcode,请转到Debug / Attach to Process菜单并查看是否列出了downLoader.

===============

我认为URL会话后台下载行为很棘手,特别是在重新启动时.我们需要至少考虑上面列出的观察结果,否则应用用户会感到困惑.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值