简体   繁体   中英

Weird iOS 8 memory management

I've noticed that iOS 8 memory management doesn't work as I might expect it to do. This may be found in a simple single view application. If you first load, for instance, 100 views the system will allocate memory for them. As a result the used memory amount will be increased (eg up to 17.1 MB). Then for some reason you decide to remove these views and get your memory back. If your app took 15 MB of memory on first load obviously you want your app to take the same amount of memory it took initially (ie 15 MB). But after removing and deinitializing all added views you won't get 15 MB but something close to it (it may be 15.2 or 15.3 MB). If you continue to consequentially add views and remove them the used memory amount will be increased every time (not so much though).

If you want to play with it:

1) Create a single view project.

2) Add a custom view class subclasses of which you will create and remove.

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++)")
    }
}

Deinitialization will be broadcasted.

3) Then go to 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)
    }
}

I added 2 buttons and created actions for them to load and unload views.

Run a project load and unload several times checking up the Debug Navigator .

Deinitialization goes perfectly but some chunk of memory isn't returned back. If you have a big project that loads and then unloads views a lot of times it turns into a problem.

My guess was that the system might have a kind of cache system. So some objects are still in the memory for further use. But this wouldn't be Apple-like.

Please let me know if you know anything about this issue.

I'm seeing a leak of between 5-80k over 100 views. Most of it seems to be various things inside of CoreAnimation, though there is a lot of caching in there, so it's not exactly clear how much "leaking" is happening versus "preemptive caching" that will amortize over many uses. Over 20 iterations, I'm seeing about 150k of total memory growth.

The short answer is: yes, don't add and remove hundreds of views. There are two good answers: first, you should typically reuse views if you're going to be adding and removing them like this (or just hiding them). If you really do need to create and destroy them all the time, consider using CALayers rather than full views. Hundreds of subviews is generally not a great approach anyway if you don't need interaction on them all (which is what views give you over layers).

The other short answer is: open a radar (bugreport.apple.com). The growth is probably a little higher than it should be, and feels like its more than just caching. When you say "might have a kind of cache system" and then "but this wouldn't be Apple-like," it's unclear what you mean. Apple caches things all the time. That's in fact incredibly common in UIKit.

But yes, UIKit has leaks. It's always had leaks. Open radars, and avoid things that exacerbate them (like adding and removing hundreds of views).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM