使用Swift-4.0.3,iOS-11.2,Xcode-9.2,iPhone-6S(或Simulator-10.0)
大约一周后,我试着弄清楚以下问题是什么问题:每当您重新进入涉及URLSession-Background-DownloadTask的ViewController时,UI都会冻结。通过重新输入,我的意思是:从VC转到Detail-VC并返回到VC ...然后再次从VC重新输入到Detail-VC。
请在github上找到我的示例项目:https://github.com/korners/Test00008
示例项目使用MZDownloadManager from mzeeshanid。我也试过其他框架 - 同样的问题。 MZDownloadManager只是我发现的一个非常好的实现。
回到问题:现在 - 至于Detail-VC的第一个条目:一切顺利运行应该(没有问题)。即使是一个已关闭的应用程序也会顺利地启动已经运行的后台 - downloadTask(没有问题 - 即progressBar和UI标签很好地更新)。
但是如果用户按下Detail-VC(NavigationController的顶部栏)上的后退按钮 - 从此刻开始,只能在冻结的默认状态下看到Detail-VC!(无论如何都没有UI更新或progressBar-movement)。
我非常感谢您的帮助!
P.S。顺便说一下,Segue本身并不会产生问题。我也尝试从故事板中实例化VC - 同样的事情:重新输入冻结UI:/
答案 0 :(得分:1)
经过一些调试后,我发现在重新进入Detail-VC时,URLSesssion的代表是 nil
。
事实证明 - (如果设置为后台任务) - 然后仍然存在先前下载的URLSession,不会创建新的URLSession对象,而是返回现有的 WITH THE OLD DELEGATE OBJECT ATTACHED < / strong> !!!
项目的设置方式:通过按下后退按钮(或保留当前的Detail-VC)将抛弃ViewController的所有内容(包括其downloadManager-property和他的委托)。因此,如果重新进入Detail-VC,则从上一次运行开始的URLSession将尝试将其委托方法发送到不再存在的URLSession-delegate! (即离开Detail-VC时被杀死的人)。
有趣的是,如果App已关闭并重新启动,则可以重新设置Background-URL-session的委托。只要应用程序正在运行,持有代表就会发生。显然。
大声思考,......我想,有一种方法可以让View对象保持活动状态(并将其作为后台URLSession作为其委托),然后每当呈现此View对象时有需要(addsubView(View)
或类似)。但总的来说,在整个App中拥有独特的View对象是一个坏主意。
我想,最好的方法是首先创建一个singleton-URLSession对象(它始终存在并且不受任何导航控制器segue&ing; ing)的影响。因此,其代表也在整个应用程序中幸存下来。
我现在带回家的消息:小心谨慎,你将自己分配给背景网站以及你的应用程序与它有什么关系(它不容易让它go-it - 即使URLSession对象(及其委托与它一起)都已经死了。;)如果你关闭应用程序并重新启动它只会释放它。
希望,我还好吗?
对此主题的任何建议或意见表示高度赞赏!
答案 1 :(得分:1)
是的,我认为你做得对。
在我的情况下,我有一个基于VC的列表(让我们称之为父VC)并详细介绍VC。细节VC将创建一个后台会话并将其自身设置为它的委托。我也注意到,如果我退出并重新输入细节VC,那就错了。我得出了相同的结论,会议正在更新第一个细节VC,我已经走了,当我从它导航时被杀死。
你看,第一个细节VC创建会话作为属性,因此它有一个指向会话的指针。它将自己设置为会话的委托,所以现在会话有一个指向它的指针。这称为循环,是内存泄漏的原因。这就是为什么第一个细节VC没有被杀死 - 会话仍然指向它。通常这可以通过在一个方向上具有弱引用来修复,但是您已经发现这里存在另一个问题:您不能只是绕过并创建具有相同标识符的多个后台会话。您需要创建一个并以单例形式保持它。