Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Download 在URLSession后台下载任务期间重新输入详细信息VC后,UI冻结_Download_Background_Swift4_Navigationcontroller_Urlsession - Fatal编程技术网

Download 在URLSession后台下载任务期间重新输入详细信息VC后,UI冻结

Download 在URLSession后台下载任务期间重新输入详细信息VC后,UI冻结,download,background,swift4,navigationcontroller,urlsession,Download,Background,Swift4,Navigationcontroller,Urlsession,使用Swift-4.0.3、iOS-11.2、Xcode-9.2、iPhone-6S(或Simulator-10.0) 大约一周后,我试图找出以下问题的症结所在:每当您重新进入涉及URLSession后台下载任务的ViewController时,UI就会冻结。通过重新输入,我的意思是:从VC到细节VC再回到VC…然后第二次从VC到细节VC重新输入 请在github上找到我的示例项目: 示例项目使用。我还尝试了其他框架——同样的问题。MZDownloadManager是我发现的一个非常好的实现 回

使用Swift-4.0.3、iOS-11.2、Xcode-9.2、iPhone-6S(或Simulator-10.0)

大约一周后,我试图找出以下问题的症结所在:每当您重新进入涉及URLSession后台下载任务的ViewController时,UI就会冻结。通过重新输入,我的意思是:从VC到细节VC再回到VC…然后第二次从VC到细节VC重新输入

请在github上找到我的示例项目:

示例项目使用。我还尝试了其他框架——同样的问题。MZDownloadManager是我发现的一个非常好的实现

回到问题:现在-关于细节VC的第一个条目:一切正常运行(没有问题)。即使是一个关闭的应用程序也会顺利地启动已经运行的后台下载任务(没有问题-即progressBar和UI标签会很好地更新)

但是如果用户按下细节VC(NavigationController的顶部栏)上的后退按钮,从现在开始,细节VC只能在冻结的默认状态下看到(不再有任何UI更新或进度条移动)

我非常感谢在这方面的任何帮助


顺便说一句,造成问题的不是赛格本身。我还尝试从故事板实例化VC——同样的事情:重新进入会冻结UI://

经过更多的调试后,我发现在重新进入详细VC时,URLSession的委托是
nil

事实证明-(如果设置为后台任务)-那么URLSession在以前的下载中仍然存在,它不会创建新的URLSession对象,而是返回现有的对象,并附加旧的委托对象

项目的设置方式:按下后退按钮(或保留当前细节VC)将丢弃ViewController中的所有内容(包括其downloadManager属性和他的委托)。因此,如果重新输入详细信息VC,则从上一次运行开始的URLSession将尝试将其委托方法发送到不再存在的URLSession委托!!!(即在离开细节VC时被杀的人)

有趣的是,如果关闭并重新启动应用程序,则可以重新设置后台URL会话的委托。显然,只有在应用程序运行时,才会出现对代理的保留

大声思考,…我想,解决这个问题的一种方法是,例如,保持视图对象处于活动状态(并将其作为其代理提供给后台URLSession),然后在需要时显示此视图对象(使用
addsubView(View)
或类似方法)。但总的来说,在整个应用程序中使用独特的视图对象是个坏主意

我想,实现这一点的最佳方法是首先创建一个单例URLSession对象(该对象始终存在,并且不受任何导航控制器segue'ing的影响)。因此,它的委托在整个应用程序中都存在

我现在的带回家的信息:请小心您将谁分配给BACKGROUND-URLSESSION作为其代理,以及您的APP-LIFECYCLE对其做了什么。(即使URLSESSION对象(及其代理一起)已死亡,它也不会轻易释放它。;)只有关闭应用程序并重新启动时,它才会释放它)

希望,我明白了,好吗


非常感谢您对本主题的任何建议或意见

是的,我想你说得对

在我的例子中,我有一个基于列表的VC(让我们称之为父VC)和详细VC。详细信息VC将创建一个后台会话,并将自己设置为该会话的代理。我还注意到,如果我退出并重新输入细节VC,就会出现问题。我得出了同样的结论,session更新了VC的第一个细节,我认为那个细节已经消失了,但当我从它导航回来时,它被杀死了


您可以看到,第一个细节VC将会话创建为一个属性,因此它有一个指向会话的指针。它将自己设置为会话上的委托,因此现在会话有一个指向它的指针。这称为循环,是内存泄漏的原因之一。这就是为什么第一个细节VC没有被杀死——会话仍然指向它。通常,通过在一个方向上使用弱引用可以解决这个问题,但正如您已经发现的,这里还有另一个问题:您不能只是到处使用相同的标识符创建多个后台会话。您需要创建一个,并将其作为一个单件保存。

感谢Nemanja的确认。它现在可以作为一个单身汉顺利工作:)