【问题标题】:UI freezes after re-entering Detail-VC during URLSession Background-DownloadTask在 URLSession Background-DownloadTask 期间重新进入 Detail-VC 后 UI 冻结
【发布时间】:2018-08-14 10:18:37
【问题描述】:

使用 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 再次 RE-ENTER。

请在 github 上找到我的示例项目:https://github.com/korners/Test00008

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

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

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

我非常感谢任何帮助!

附:顺便说一句,造成问题的不是 Segue 本身。我还尝试从情节提要中实例化 VC - 同样的事情:重新输入会冻结 UI:/

【问题讨论】:

    标签: download background swift4 navigationcontroller urlsession


    【解决方案1】:

    是的,我认为你没看错。

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

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

    【讨论】:

    • 感谢 Nemanja 的确认。它现在可以作为单身人士顺利工作:)
    【解决方案2】:

    经过一些调试,我发现在 Detail-VC 重新进入时,URLSesssion 的委托是 nil

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

    项目的设置方式:按下后退按钮(或离开当前的 Detail-VC)将丢弃 ViewController 中的所有内容(包括它的 downloadManager-property 和他的委托)。因此,如果重新进入 Detail-VC,那么从先前运行中启动的 URLSession 将尝试将其委​​托方法发送到不再存在的 URLSession-delegate !!! (即离开 Detail-VC 时被杀的那个)。

    有趣的是,如果 App 关闭并重新启动,则可以重新设置 Background-URL-session 的委托。显然,只有在应用程序运行时才会对委托进行保留。

    大声思考,...我想解决这个问题的一种方法是,例如保持一个 View-object 活动(并将其作为其委托给 background-URLSession),然后在任何时候呈现这个 View-object有需要(addsubView(View) 或类似的)。但总的来说,在整个 App 中拥有唯一的 View-objects 是个坏主意。

    我想,解决这个问题的最好方法是首先创建一个单例 URLSession 对象(它在整个过程中都存在并且不受任何导航控制器 segue'ing 的影响)。因此,它的委托在整个应用程序中也存在。

    我现在的主要信息:小心你分配给背景 URLSESSION 的人作为它的代表,以及你的应用程序生命周期对它的作用(它不会轻易放弃它 - 即使 URLSession 对象(以及它的委托连同它)都死了。;) 只有在你关闭应用程序并重新启动时它才会放手)

    希望,我明白了吗?

    对此主题的任何建议或cmets 高度赞赏!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-03
      相关资源
      最近更新 更多