更改根视图控制器不会释放同一个窗口上的先前视图控制器

问题描述:

我的应用程序启动时使用初始视图控制器(我们称之为StartVC)。现在,当用户按下继续按钮时,我将在StartVC之上呈现一个导航堆栈(可称为RegisterVC)。这个导航堆栈将包含5个视图控制器,每当用户向前移动按钮操作时,我都会按下它。在第五个视图控制器之后,我开始一个新的导航堆栈(我们称之为LoginVC)。更改根视图控制器不会释放同一个窗口上的先前视图控制器

现在我的使用情况是我不想让StartVC & RegisterVC驻留在内存,因为它们是没有用的,一旦用户完成注册。为了实现这一点,我改变了AppDelegate中窗口的根视图控制器LoginVC

下面是我试过的RegisterVC第五视图控制器上的选项:更改keywindow

1)

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)将前一个根视图控制器设置为零,然后分配一个新视图控制器。

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

4)我也尝试了直接从AppDelegate的上述选项,而不是从第五个视图控制器做它。

以上所有的选项,我试着通过在所有视图控制器上查看deinit进行调试,但是没有一个被取消分配。另外,我可以在xcode Debug View Hierarchy中看到LoginVC下的第五个视图控制器。

由于没有从内存中删除它们,我面临的实际问题是在呈现LoginVC之后,我有一个视图控制器,其背景色alpha更少。正因为如此,我在其下看到RegisterVC 5th视图控制器。

对此赞赏的任何帮助...

+1

我建议使用[ “调试内存图”](https://*.com/questions/30992338/how-to-debug-memory-leaks-when-leaks-instrument-does-not -show-them/30993476#30993476)功能,以查看对这些旧视图控制器保持强大的参考。 – Rob

+0

你应该在这里回答:http://*.com/a/27153956/849645。如果你的问题与我的问题相同,这就为我解决了问题。 – CMont

我认为rootViewController设置不是问题。也许你在其他视图控制器中有一个保留周期,可以阻止它们被释放。

有很多方法可能会意外地执行此操作(捕获对块中自身的强引用,不将代表或其他后引用标记为弱等)。

你可能可以通过仪器找出它。这里有一个教程:http://samwize.com/2016/05/30/finding-retain-cycle-with-instruments/

+0

或使用Rob的调试内存图的建议(请参阅您的问题的评论) –

+0

是啊,看起来你们是对的,似乎有一个保留周期,但我无法找出它发生的地方......我跟着'调试内存图表'和'工具',但没有结束......我谨慎地管理内部关闭和'弱代理引用'中的'弱自我',但它仍然隐藏在某个地方......我会发现一次更新在哪里发生......感谢您的快速回复。 – Venkat

+0

Hi @Venkat对此有何更新?我正面临类似的问题,因为前一个控制器在切换控制器时仍然可见。 –

在设置新的根视图控制器之前,删除以前的根视图控制器。

private func removePreviousViewController() { 
    let previousViewController = self.window?.rootViewController 
    previousViewController?.dismiss(animated: true, completion: { 
     previousViewController?.view.removeFromSuperview() 
    }) 
}