Memory leak with SpriteKit in Collection View Cells

661 views Asked by At

I am using SpriteKit to do animations in UICollectionViewCell's in a UICollectionView. The scene has a single sprite that I'm animating using SKAction's. The contentView of each cell has its own SKView/SKScene. I'm running into a memory leak. When I look at this in the Allocations Instrument in Xcode 6.3, I see that with each new cell, a pair of > 1MB allocations, one attributed to "SKView set_context", the other attributed to allocateWCMemory GLEngine".

Within each UICollectionViewCell, it's pretty standard stuff. I'm creating other (unrelated to the animation) UIView subviews and adding them to the contentView.

One thing that is odd and perhaps related is that I don't get the deinit method of the UICollectionViewCell's consistently called.

Thoughts?

Updates:

1) This seems directly related to the animations and not so much to the collection views. If I just turn off the animation part of the code, I don't seem to be getting the memory leak. Or at least not as much memory is leaking. In this case, the SKScene/SKView are still getting allocated (per collection view cell), but I just don't animate the sprite. I should also add that in this case, with the animation disabled, I get all my deallocation breakpoints hit where they should be hit (e.g., the UICollectionViewCell deinit method).

2) Now I've added the animation back in, but I just do one cycle through it. I had been doing repeated animations (the same animation, just repeated, controlled with a timer). When I do it just once and stop, no memory leak. So, the issue seems to stem from my repeated animations.

2

There are 2 answers

0
Chris Prince On BEST ANSWER

This memory leak appears to have little or nothing to do with SpriteKit or Collection Views. I was presenting the UICollectionView in a modal view controller, and that (Objective C) modal had an issue that seems to have only arisen when bridging it to Swift. The containing modal view controller was not getting deallocated. Thus, the objects it contained (such as the UICollectionView, and within that, the SKView/SKScene) were not getting deallocated.

That modal presents from a UINavigationController. Using this Objective-C class bridged to Swift, I'm finding it necessary to add in the line:

// popupNavController is the UINavigationController used to present the modal view controller
self.popupNavController.viewControllers = nil;

when I'm dismissing the modal.

1
Good Doug On

Without looking at the code it is hard to tell, but there is one thing you should look for: Do any of your SKActions contain a block that refers to self? If so, that can cause a retain cycle. You will need to get a weak reference to self in that case (it will be different between Swift and Objective C, but they will both need it) A good explanation (and decent Swift examples) can be found in this post.