2
votes

Our app (iOS 9.1, Xcode 7.1) uses SpriteKit and is crashing with a "Terminated due to memory issue." I started removing more and more code and finally discovered that the simple act of creating and discarding plain SKScene instances will exhaust memory. In fact, something as simple as:

while true {
    _ = SKScene(size: CGSize(width: 100.0, height: 100.0))
}

will eventually cause the app to crash with the same memory issue. I watch it in the debug navigator, and the "Memory" value rises quickly and then the app crashes. Using a different class, such as:

while true {
    _ = [Int](count:1000, repeatedValue:0)
}

will chew up a lot of CPU, but the instances are released cleanly and memory is never exhausted.

I tried subclassing SKScene and adding a deinit that printed a message. The message was printed just as I would expected, but the memory ran out anyway.

The problem for us: we subclass SKScene with a lot of extra stuff, and the app runs out of memory if we create and discard more the 10 or 12 instances (sequentially) over the execution life of the app. There is never a time when more than two instances should be alive. We've reviewed the code and there are no strong reference cycles.

Does SKScene do anything that requires us to do something special to avoid memory issues of this type?

1
Maybe have a global variable called activeScene, and just rerun the constructor on it every time you want a new scene? This may solve the memory issue. If you also need to run transitions, maybe have a transitionScene global variable as well? Kinda a weird workaround, but may work.Gliderman
Very clever. I read somewhere that scenes are cached, and I'm guessing that that cache is leaving something dirty. The idea of caching our own scenes to avoid the system cache is sneaky but is worth a try. Bravo, great suggestion.Dan Leifker

1 Answers

1
votes

You are right, with this code the used memory does grow up.

while true {
    _ = SKScene(size: CGSize(width: 100.0, height: 100.0))
}

But I don't think it is something directly related to SKScene.

When the memory does grow up

Infact the same memory behaviour does happen with other types (classes or structs) like UIButton or big arrays of strings.

Here the used memory does grow up.

while true {
    _ = UIButton(type: .DetailDisclosure)
}

Here the used memory does grow up as well.

while true { 
    _ = [String](count:100000000000, repeatedValue:"Hello world")
}

When the memory does NOT grow up

I noted that waiting a second at the end of each while iteration does solve the problem.

while true {
    _ = UIButton(type: .DetailDisclosure)
    sleep(1)
}

Conclusions

My idea is that the used memory does grow up simply because the system has not enough time to free the memory for the old objects/values.