今天Widget每次刷新时会占用更多内存,最终崩溃

时间:2018-04-10 15:34:48

标签: ios memory-leaks today-extension ios8-today-widget ios10-today-widget

我正在研究今日小工具,并遇到内存问题。

当我运行小部件并监视内存使用情况Xcode时,小部件在首次启动时使用大约15MB。然后,当我从小部件屏幕向后滑动时,它会上升到大约16MB。

每次我轻扫并返回时,内存使用量会增加约0.5-1.5MB。当我这样做时,我会收到内存警告(didReceiveMemoryWarning()被调用),最终,通过更多扫描,窗口小部件崩溃。

在iPhone X上进行测试时,所有这些症状都会发生。在模拟器上,小部件开始使用大约50兆字节,这看起来很奇怪,但它有相同的行为,每次我轻扫时内存使用率都会上升并向后滑动。

我试过用Instruments来分析这个,但是我只能让乐器显示开始时(当我第一次启动Widget时)会发生什么,并且当我向后滑动时它不会继续运行。

通过消除过程(评论我的小部件的实际功能),只有UI代码仍然存在时,问题仍然存在。 这让我觉得我的UI方法存在问题。

我过去曾构建过Today Widgets,但始终使用Interface Builder。这次我决定以编程方式构建接口。当我查看使用Interface Builder构建的其他Today Widgets时,我没有看到每次刷新时增加内存使用量的相同行为。

首先,我将所有UI元素设置为私有惰性变量,如下所示:

private lazy var mainStackView: UIStackView = {
    let stackView = UIStackView()
    stackView.distribution = .fillEqually
    stackView.translatesAutoresizingMaskIntoConstraints = false
    return stackView
}()

然后,在viewDidLoad()中,我将视图添加到TodayViewController的视图中,但有一些限制,如下所示:

view.addSubview(mainStackView)

let stackViewLeadingConstraint = mainStackView.leadingAnchor.constraintEqualToSystemSpacingAfter(view.leadingAnchor, multiplier: 1)
let stackViewTopConstraint = mainStackView.topAnchor.constraintEqualToSystemSpacingBelow(view.topAnchor, multiplier: 1)
let stackViewTrailingConstraint = view.trailingAnchor.constraintEqualToSystemSpacingAfter(mainStackView.trailingAnchor, multiplier: 1)
let stackViewBottomConstraint = view.bottomAnchor.constraintEqualToSystemSpacingBelow(mainStackView.bottomAnchor, multiplier: 1)

view.addConstraints([stackViewLeadingConstraint, stackViewTopConstraint, stackViewTrailingConstraint, stackViewBottomConstraint])

由于我是以编程方式构建UI的新手,是否有任何使用此方法的内容似乎明显不正确并且看起来可能会导致内存泄漏?

我甚至尝试评论我的所有代码并使用基本空白UIViewController运行它,其中视图生命周期函数甚至没有做任何事情,我仍然遇到内存泄漏。这让我觉得当我以编程方式构建我不做的界面时,我应该做些什么。

每次今日小工具出现时,似乎某些东西没有被释放并在内存中被复制。我很感激有关如何找到未发布内容的任何建议并强制系统发布它。谢谢!

解决

感谢Christopher Pickslay提供的故障排除提示,我能够找到问题所在。结果证明是我的错。为了解决以前不相关的问题,我打开了方案中的Zombie Objects,我仍然启用了它。一旦我把它关掉,这个问题就消失了。这是我正在谈论的设置: Zombie Objects checkbox in Xcode

1 个答案:

答案 0 :(得分:2)

我没有看到你如何构建UI的任何问题(从目前为止你所分享的内容)。而不是仪器,尝试使用Memory Graph Debugger来查找泄漏。

Memory Graph Debugger

它将暂停调试器,您可以使用顶部栏浏览所有的定位以及每个实例的指向。打开内存图调试器,查看图形,然后取消暂停并将屏幕上的链接滚动几次,然后再次打开内存图调试器。这应该可以让你更好地了解什么是泄漏以及什么是持有它。