怪异iOS8 内存管理

Weird iOS 8 memory management

我注意到 iOS 8 内存管理没有像我预期的那样工作。这可以在简单的单视图应用程序中找到。例如,如果您首先加载 100 个视图,系统将为它们分配内存。因此,使用的内存量将增加(例如,高达 17.1 MB)。然后出于某种原因,您决定删除这些视图并恢复记忆。如果您的应用程序在第一次加载时占用 15 MB 的内存,显然您希望您的应用程序占用与最初占用的内存量相同的内存量(即 15 MB)。但是在删除和取消初始化所有添加的视图之后,您不会得到 15 MB,而是接近它的东西(可能是 15.2 或 15.3 MB)。如果您继续相应地添加视图并删除它们,每次使用的内存量都会增加(虽然不是很多)。

想玩的话:

1) 创建单视图项目。

2) 添加您将创建和删除的自定义视图 class 个子 class。

var deinited = 0

class TestView: UIView {
    let label: UILabel

    init(text: String, frame: CGRect) {
        label = UILabel(frame: CGRectMake(0, 0, frame.width, frame.height))
        label.text = text
        super.init(frame: frame)
        addSubview(label)
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    deinit {
        println("\(deinited++)")
    }
}

将广播取消初始化。

3) 然后转到ViewController

class ViewController: UIViewController {
    var views = [TestView]()

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func load(sender: AnyObject) {
        let rect = CGRectMake(0, 0, 100, 60)
        for i in 0...99 {
            let testView = TestView(text: "\(i)", frame: rect)
            testView.hidden = true
            views.append(testView)
            view.addSubview(testView)
        }
    }

    @IBAction func unload(sender: AnyObject) {
        for testView in views {
            testView.removeFromSuperview()
        }

        views.removeAll(keepCapacity: false)
    }
}

我添加了 2 个按钮并为它们创建了加载和卸载视图的操作。

运行 项目加载和卸载多次检查 Debug Navigator

取消初始化进行得很顺利,但一些内存块没有返回。如果您有一个大项目,需要多次加载和卸载视图,这就会成为一个问题。

我的猜测是系统可能有一种缓存系统。所以一些对象仍然在内存中以供进一步使用。但这不会像苹果那样。

如果您对此问题有任何了解,请告诉我。

我发现在 100 次观看中泄漏了 5-80k。大部分似乎是 CoreAnimation 内部的各种东西,尽管那里有很多缓存,所以不清楚有多少 "leaking" 正在发生,而 "preemptive caching" 会分摊到许多用途中。超过 20 次迭代,我看到总内存增长了大约 150k。

简短的回答是:是的,不要添加和删除数百个视图。有两个很好的答案:首先,如果您要像这样添加和删除视图(或只是隐藏它们),通常应该重用视图。如果你确实需要一直创建和销毁它们,请考虑使用 CALayer 而不是完整视图。如果您不需要对所有子视图进行交互(这是视图为您提供的图层),那么数百个子视图通常不是一个好方法。

另一个简短的回答是:打开雷达(bugreport.apple.com)。增长可能比应有的高一点,感觉不仅仅是缓存。当你说 "might have a kind of cache system" 然后 "but this wouldn't be Apple-like," 时,你的意思不清楚。苹果一直在缓存东西。事实上,这在 UIKit 中非常普遍。

但是,是的,UIKit 存在漏洞。一直有漏水的打开雷达,避免加剧它们的事情(比如添加和删除数百个视图)。