奇怪的iOS 8内存管理

时间:2015-04-27 18:25:40

标签: ios swift memory memory-management

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

如果你想玩它:

1)创建单个视图项目。

2)添加您要创建和删除的自定义视图类子类。

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

取消初始化非常完美,但是一些内存不会被退回。如果你有一个很大的项目加载然后卸载视图很多次就会变成一个问题。

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

如果您对此问题了解任何事情,请与我们联系。

1 个答案:

答案 0 :(得分:2)

我在100次观看时发现5-80k之间的泄漏。其中大部分内容似乎都是CoreAnimation中的各种内容,尽管其中有很多缓存,所以它并不清楚有多少"泄漏"正在发生与#34;抢先缓存"将摊销多种用途。超过20次迭代,我看到总内存增长约150k。

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

另一个简短的回答是:打开雷达(bugreport.apple.com)。增长可能比它应该高一点,并且感觉不仅仅是缓存。当你说"可能有一种缓存系统"然后"但这不会像苹果一样,"它不清楚你的意思。 Apple一直在缓存事物。事实上,这在UIKit中非常普遍。

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