MetalKit: MTKView stays in memory when it supposed to be released.
| Originator: | berkutvlad | ||
| Number: | rdar://23977735 | Date Originated: | 21-Dec-2015 11:39 PM |
| Status: | Open | Resolved: | |
| Product: | iOS SDK | Product Version: | 9.x |
| Classification: | Reproducible: | Always |
sample project: https://www.dropbox.com/s/axgswutjuoddr0m/Rdar.zip?dl=0
Summary:
Once MTKView was created it stays in memory forever. I’d faced with this problem in real project, but for sake of simplicity I’ve created two test projects to focus on the problem. They're in attachments.
MTKViewReleaseProblem_XIB_version project consists of RootViewController which is responsible for presenting ViewController. ViewController has an MetalView weak outlet reference from corresponding xib. MetalView is a subclass of MTKView which does nothing except logging of its creation and destruction. But actually destruction log doesn't appear. This project shows the problem when we use MTKView in conjunction with xibs.
MTKViewReleaseProblem_non_XIB project consists of ViewController which is responsible for presenting MetalViewController. MetalViewController has an MetalView instance as property that is initialized in viewWillAppear.MetalView is a subclass of MTKView which does nothing except logging of its creation and destruction. But actually destruction log don't appear. This project shows the problem when we create MTKView programmatically(from code).
Both projects show deallocation issue of MTKView instances, which are not even initialized with any data.
Steps to Reproduce:
Case 1:
0. Launch MTKViewReleaseProblem_XIB_version project from XCode.
1. Tap “Present” button to show ViewController from RootViewController.
2. See "MetalView initWithCoder” in console window(‘cause MetalView has this log statement)
3. Tap “Dismiss” button to dismiss ViewController and deallocate it.
4. See "ViewController dealloc” message which ViewController has in its dealloc method.
Case 2:
0. Open MTKViewReleaseProblem_XIB_version in XCode.
1. Launch with profiler.
2. Choose ‘Allocations’ template.
3. Enter ‘MetalView’ in ‘Instrument detail field’ to find MetalView instances.
4. On device tap “Present” button to show ViewController from RootViewController.
5. On device tap “Dismiss” button to dismiss ViewController and deallocate it.
6. Repeat steps 4-5 several times.
Case 3:
0. Launch MTKViewReleaseProblem_non_XIB project from XCode.
1. Tap “Present” button to show MetalViewController from ViewController.
2. See "MetalView initWithFrame:device:” in console window(‘cause MetalView has this log statement)
3. Tap “Dismiss” button to dismiss MetalViewController and deallocate it.
4. See " dealloc MetalViewController” message which ViewController has in its dealloc method.
Case 4:
0. Open MTKViewReleaseProblem_non_XIB in XCode.
1. Launch with profiler.
2. Choose ‘Allocations’ template.
3. Enter ‘MetalView’ in ‘Instrument detail field’ to find MetalView instances.
4. On device tap “Present” button to show MetalViewController from ViewController.
5. On device tap “Dismiss” button to dismiss MetalViewController and deallocate it.
6. Repeat steps 4-5 several times.
Expected Results:
Case 1:
MetalView's dealloc message in console window.
Case 2:
In Details->Statistics pane there are no records in ‘Presistent’ column for MetalView.
Case 3:
MetalView's dealloc message in console window.
Case 4:
In Details->Statistics pane there are no records in ‘Presistent’ column for MetalView.
Actual Results:
Case 1:
Despite of ViewController’s dealloc message there isn’t corresponding MetalView's dealloc message. But it should be.
Case 2:
In Details->Statistics pane there are several ‘Persistent’ instances of MetalView(actually how many times steps 4-5 were performed). In Details->AllocationList pane we can see instances of MetalView and 'Responsible Caller’ for them - [UIClassSwapper initWithCoder:] what wasn't actually created by me.
Case 3:
No MetalView’s dealloc message
Case 4:
In Details->Statistics pane there are several ‘Persistent’ instances of MetalView(actually how many times steps 4-5 were performed). In Details->AllocationList pane we can see instances of MetalView and 'Responsible Caller’ for them - [MetalViewController viewWillAppear:] what is quite strange if we’ll look at implementation.
Version:
iOS 9.1[13B143] and iOS 9.0.2[13A452]
Notes:
Configuration:
iPhone 6 plus
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!
Potential (hacky) fix
Subclassing MTKView and implementing the following in -didMoveToSuperview solves the issue, pointing to a CADisplayLink that is never invalidated / doesn't release its target.
public override func didMoveToSuperview() { super.didMoveToSuperview() if let link = self.valueForKey("_displayLink") as? CADisplayLink where superview == nil { link.invalidate() } }