更改根视图控制器并不会释放同一窗口中先前的视图控制器。

11
我的应用程序会启动一个初始视图控制器(我们称其为StartVC)。现在,当用户按下一个继续按钮时,我会在StartVC之上呈现一个导航栈(我们称其为RegisterVC)。每当用户通过按钮操作向前移动时,我都会将5个视图控制器推送到该导航栈中。在第5个视图控制器之后,我会启动一个新的导航栈(我们称其为LoginVC)。
现在我的使用情况是:一旦用户完成注册,我就不希望StartVCRegisterVC存储在内存中,因为它们没有任何用处。为了实现这一点,我正在更改AppDelegate窗口的根视图控制器为LoginVC 以下是我尝试过的RegisterVC的第五个视图控制器的选项:
1)更改keywindow
    UIApplication.shared.keyWindow?.rootViewController = LoginVC
    UIApplication.shared.keyWindow?.makeKeyAndVisible()

2) 更改窗口

   let appDelegate = UIApplication.shared.delegate as! AppDelegate
   appDelegate.window?.rootViewController = LoginVC
   appDelegate.window?.makeKeyAndVisible()

3) 在分配新的根视图控制器之前,将先前的根视图控制器设置为nil。

   let appDelegate = UIApplication.shared.delegate as! AppDelegate
   appDelegate.window?.rootViewController = nil
   appDelegate.window?.rootViewController = LoginVC
   appDelegate.window?.makeKeyAndVisible()

4) 我还尝试了从AppDelegate直接执行上述选项,而不是从第5个视图控制器中执行。

在尝试了以上所有选项后,我尝试通过查看所有视图控制器的 deinit 来进行调试,但它们都没有被销毁。另外,我可以在 xcode Debug View Hierarchy 中看到LoginVC下的第五个视图控制器。

由于没有将它们从内存中删除,我遇到的实际问题是,在展示LoginVC之后,我的一个视图控制器的背景颜色透明度较低。因此,我看到了位于其下方的RegisterVC第五个视图控制器。

如果有任何帮助,将不胜感激...


1
我建议使用“调试内存图”功能来查看是什么在保持对那些旧视图控制器的强引用。链接 - Rob
你可以在这里找到答案:https://dev59.com/IF8d5IYBdhLWcg3wgiT4#27153956。如果你的问题和我的一样,这个方法对我有用。 - CMont
1个回答

5
我认为rootViewController设置并不是问题所在。或许您的其他视图控制器存在保留循环,导致它们无法被解除分配。 有很多可能会意外发生这种情况(在块中捕获强引用、未将委托或其他反向引用标记为弱引用等)。
您可以通过Instruments找到问题所在。以下是一个教程:http://samwize.com/2016/05/30/finding-retain-cycle-with-instruments/

或者使用Rob的建议,调试内存图(请参见您问题下的评论)。 - Lou Franco
是的,看起来你们是对的,似乎存在一个保留循环,但我无法找出它发生在哪里...我遵循了“调试内存图”和“仪器”的方法,但却一无所获...我正在谨慎地处理闭包中的“弱引用self”和“弱引用委托”,但它仍然隐藏在某个地方...一旦我找到它发生的地方,我会发布更新...感谢您的快速回复。 - Naveen
嗨@Naveen。你最终找到了保留环的原因吗?我遇到了非常相似的问题,调试并没有帮助我找到问题的根源。 - WedgeSparda
没有@WedgeSparda,我没有找到原因。所以我通过在更改根控制器时解雇它来解决它(我觉得我使用了一些动画,以便用户不会看到它发生,但因为时间已经很长时间过去了,我不确定)。 - Naveen
@Naveen,你能贴一下你所做的例子吗?我认为你只是在动画之前放置了一个dismiss,或者可能是在它的完成块上。 - WedgeSparda
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接