切换故事板场景时从内存中删除对象

时间:2014-10-28 12:49:38

标签: memory swift storyboard

我以编程方式创建所有显示对象,并将它们添加到我的故事板场景子视图中。

例如:

let button: UIButton = UIButton( frame: CGRect( x: 0, y: 0, width: 160, height: 50 ) )
self.view.addSubview( button )

在更改故事板场景时,我遇到了巨大的内存泄漏(内存使用率在每次场景更改之间几乎翻倍),这当然表明在更改场景时这些对象不会被自动删除。我在Swift中已经阅读了一些关于垃圾收集的内容,但是没有找到关于这个特定用例的更多信息。

通过更改故事板场景,我的意思是通过当前的视图控制器,如下所示:

self.presentViewController( targetController, animated: true, completion: nil )

所以说,我的问题是:

1)删除对象可以这样做:

button.removeFromSubview()
button = nil

正确?

2)有没有办法在循环中删除插入到视图子视图中的任何对象,并将其指定为nil以完全删除与该对象关联的任何引用?我可以一个一个地删除它们,但这是一个痛苦的任务。

3)在更改场景后,无论如何都要从内存中自动删除对象?这将是最好的解决方案。

非常感谢解决方案的一个例子。

提前致谢。

2 个答案:

答案 0 :(得分:2)

有些事情可能会澄清:

1)通过故事板(标记为@IBOutlet)添加的按钮很弱;你不需要把它们弄掉,因为你对它们的引用并没有把它们留在记忆中。

2)presentViewController可能不会以您期望的方式行事。最重要的是,不使用新的视图控制器替换现有的视图控制器;它"礼物"来自旧视图控制器的新视图控制器。为了说明这一点,您可以从新的视图控制器调用self.presentingViewController,它将为您提供对前一个视图控制器的引用;它还在记忆中。

但是,视图控制器并不是超级大,并且当它们不在屏幕上时,它们的视图会被卸载。但是,如果您在呈现视图控制器中持有一些大型资源,则这些资源将持续存在。我建议通过在viewWillAppear / viewDidAppear(而不是viewDidLoad)中加载这些资产来解决这个问题,然后在prepareForSegue:或viewDidDisappear中卸载它们(我认为还有一些长期存在的问题,而didDisappear没有得到一致的调用吗?我有那边有某种心理旗帜,但我不确定消息来源是什么......)

或者,如果您真正想要做的是完全更改为新的根视图控制器,您可以通过AppDelegate的.window属性执行此操作,如下所示:

let storyboard = UIStoryboard(named: "NewStoryboard", bundle: nil)
let newVC = storyboard.instantiateInitialViewController
UIApplication.sharedApplication().delegate.window.rootViewController = newVC
但是,我不会过度使用这个;它可能在您首次启动时显示教程的地方非常有用,然后又想要加载普通的视图层次结构。

答案 1 :(得分:0)

如果通过更改场景意味着您要向堆栈添加新视图,那么我的理解是前一个视图仍然存在,只是等待再次弹出到堆栈的顶部,因此您的对象不应该是除去。如果我有这个错误,有人会纠正我。无论如何,从视图中删除所有对象的代码是:

for sv in view.subviews {
    sv.removeFromSuperview()
}