问题描述
使用Swift-4.0.3,iOS-11.2,Xcode-9.2,iPhone-6S(或Simulator-10.0)
Using Swift-4.0.3, iOS-11.2, Xcode-9.2, iPhone-6S (or Simulator-10.0)
大约一个星期以来,我试图弄清楚以下问题是什么问题:每当您重新输入涉及URLSession-Background-DownloadTask的ViewController时,UI都会冻结.重新输入的意思是:从VC到Detail-VC,然后再回到VC ...,然后第二次从VC重新输入到Detail-VC.
Since about a week I try to figure out what the problem is with the following issue: The UI freezes whenever you re-enter a ViewController that involves a URLSession-Background-DownloadTask. By re-entering, I mean: Going from VC to Detail-VC and back to VC...and then RE-ENTER a second time from VC to the Detail-VC.
请在github上找到我的示例项目: https://github.com/korners/Test00008
Please find my example project here on github : https://github.com/korners/Test00008
该示例项目使用了来自mzeeshanid的MZDownloadManager .我也尝试了其他框架-同样的问题.我发现MZDownloadManager只是一个非常好的实现.
The sample project uses the MZDownloadManager from mzeeshanid. I tried also other frameworks - same issue. The MZDownloadManager is just a very nice implementation I found.
回到问题:现在-关于Detail-VC的第一个条目:一切运行正常(应该没有问题).甚至关闭的应用程序也可以顺利加入已经运行的background-downloadTask(没有问题-即ProgressBar和UI标签可以很好地更新).
Back to the issue: Now - as for the first entry of the Detail-VC: Everything runs smoothly as it should (no issues). Even a closed App will smoothly kick-in to the already running background-downloadTask (no issues - i.e. progressBar and UI-labels update nicely).
但是,如果用户按下Detail-VC(导航控制器顶部栏)上的后退按钮-从这一刻起,Detail-VC仅在冻结的默认状态下可见!(不再进行UI更新或ProgressBar移动).
But if the user presses the back button on the Detail-VC (top bar of the NavigationController) - from this moment on, the Detail-VC can only be seen in a frozen default-state ! (no UI updates or progressBar-movements anymore whatsoever).
非常感谢您对此提供的任何帮助!
I highly appreciate any help on this !
P.S.顺便说一句,不是问题本身就是由塞格造成的.我还尝试了从情节提要中实例化VC-同样,重新输入将冻结UI:/
P.S. By the way, it is not the Segue per se that creates the problems. I also tried instantiating VC from the storyboard - and the same thing: RE-ENTERING freezes the UI :/
推荐答案
经过更多调试后,我发现在Detail-VC重新输入时,URLSesssion的委托是 nil
strong>.
After some more debugging I figured out that at the re-enter of the Detail-VC, the delegate of the URLSesssion is nil
.
事实证明-(如果设置为后台任务)-那么上一次下载的URLSession仍然存在,不会创建新的URLSession对象,而是返回现有的已附着旧的代理对象 !!!
As it turns out - (if set up as background-task) - then the URLSession still existing from a previous download, does not create a new URLSession object but returns the existing one WITH THE OLD DELEGATE OBJECT ATTACHED !!!
项目的设置方式:按下后退按钮(或退出当前的Detail-VC)将丢弃ViewController的所有形式(包括其downloadManager-property和他的委托).因此,如果重新输入Detail-VC,则从上一次运行开始的URLSession将尝试将其委托方法发送到不再存在的URLSession-delegate! (即离开Detail-VC时被杀死的人).
The way the project was set up: By pressing the back-button (or leaving the current Detail-VC) will throw away everything form that ViewController (including its downloadManager-property and his delegate). Therefore, if re-entering the Detail-VC then the URLSession kicking in from previous run will try to send its delegate-methods to the URLSession-delegate that no longer exists !!! (i.e. the one killed when leaving the Detail-VC).
有趣的是,如果关闭并重新启动该应用程序,则可以重新设置Background-URL-session的委托.显然,只有在应用程序运行时才发生代表委托.
Interestingly enough, if the App is closed and re-started, then the delegate of the Background-URL-session can be newly set. The holding on to the delegate is only happening as long as the App is running, obviously.
大声地想,...一种解决方法,例如,我认为是保持一个View对象处于活动状态(并将其作为委托传递给background-URLSession),然后在任何时候呈现此View对象有需要(使用addsubView(View)
或类似名称).但总的来说,在整个应用程序中拥有唯一的View对象是一个坏主意.
Thinking loudly, ...one way to go about this, I guess, is for example by keeping a View-object alive (and give it to the background-URLSession as its delegate) and then presenting this View-object whenever there is a need (with addsubView(View)
or similar). But in general, it is a bad idea to have unique View-objects throughout the App.
我猜想,解决此问题的最佳方法是首先创建一个单例URLSession对象(该对象始终存在,并且不受任何导航控制器选择的影响).因此,它的代表也可以在整个App中生存.
The best way to go about this, I guess, is to create a singleton-URLSession-object in the first place (that survives throughout and is not affected by any Navigation-controller segue'ing). And therefore also its delegate survives throughout the App.
我现在的带回家的消息是:请谨慎对待您将其分配给后台URL的权限,以及它对应用程序生命的影响(不会轻易放手它-即使URLSession对象(及其委托也一起)都没有死.;)仅当您关闭应用程序并重新启动时,它才会放开它
My take-home message for now: BE CAREFUL WHO YOU ASSIGN TO THE BACKGROUND-URLSESSION TO BE ITS DELEGATE AND WHAT YOUR APP-LIFECYCLE DOES WITH IT (it won't easily let go of it - not even if the URLSession object (and its delegate together with it) are dead. ;) It will only let go of it if you close the App and re-start)
希望,我没事吧?
对此主题的任何建议或评论都非常感谢!
Any suggestions or comments to this subject highly appreciated !
这篇关于在URLSession Background-DownloadTask中重新输入Detail-VC之后,UI冻结的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!