Re: iOS 9: Adding CALayer to self.view.layer causes EXC_BAD_ACCESS
Re: iOS 9: Adding CALayer to self.view.layer causes EXC_BAD_ACCESS
- Subject: Re: iOS 9: Adding CALayer to self.view.layer causes EXC_BAD_ACCESS
- From: David Duncan <email@hidden>
- Date: Tue, 06 Dec 2016 12:24:22 -0800
> On Dec 6, 2016, at 11:44 AM, Carl Hoefs <email@hidden> wrote:
>
> I get the following crash in my iOS 9 app simply by adding a CALayer to the current view controller's self.view.layer and then dismissing the current view controller. Simplified code:
>
> @property (strong,nonatomic) CALayer *layer;
> . . .
> _layer = [[CALayer alloc] init];
> [_layer setDelegate: self];
> [self.view.layer addSublayer:_layer];
>
> Upon dismissing the VC:
>
> [self dismissViewControllerAnimated:YES completion:nil];
>
> The following exception occurs:
>
> (lldb) bt
> * thread #1: tid = 0x121bd, 0x22c2c68a libobjc.A.dylib`objc_retain + 10, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xb0000010)
> frame #0: 0x22c2c68a libobjc.A.dylib`objc_retain + 10
> frame #1: 0x27a2a22a UIKit`-[UIView(Hierarchy) subviews] + 330
> frame #2: 0x27b3e1ea UIKit`discardEngineRecursive + 118
> frame #3: 0x27a2fd06 UIKit`-[UIView dealloc] + 630
> frame #4: 0x2336cd98 CoreFoundation`-[__NSDictionaryM dealloc] + 132
> frame #5: 0x22c2cf8a libobjc.A.dylib`objc_object::sidetable_release(bool) + 150
> frame #6: 0x22c2d3cc libobjc.A.dylib`(anonymous namespace)::AutoreleasePoolPage::pop(void*) + 388
> frame #7: 0x23363f30 CoreFoundation`_CFAutoreleasePoolPop + 16
> frame #8: 0x23415c56 CoreFoundation`__CFRunLoopRun + 1598
> frame #9: 0x233641c8 CoreFoundation`CFRunLoopRunSpecific + 516
> frame #10: 0x23363fbc CoreFoundation`CFRunLoopRunInMode + 108
> frame #11: 0x24980af8 GraphicsServices`GSEventRunModal + 160
> frame #12: 0x27a9c434 UIKit`UIApplicationMain + 144
> * frame #13: 0x001b655e ProteinFold`main(argc=1, argv=0x0043bbc8) + 122 at main.m:14
This is due to the confluence of a few UIKit implementation details. The bottom line is that UIKit is trying to iterate the subviews of your view controller’s view, encounters your layer, and tries to retain the layer’s delegate. Because the layer’s delegate is assign (not weak) and the view controller has already been deallocated, this explodes taking your app with it.
Your safest bets are to either clear the delegate of the layer at an appropriate time (possibly in your view controller’s dealloc is all that is necessary), or to use a UIView instead of a raw CALayer in this case. Removing the layer would also suffice, as that would prevent UIKit from seeing it at the time in question. Making the layer weak is probably causing your reference to deallocate before it can be added to the layer tree, which is why it doesn’t display in that case.
>
> If I remove the CALayer first before the -dismissViewControllerAnimated:completion:, it doesn't crash:
>
> [layer removeFromSuperlayer];
>
> Why do I need to explicitly remove my added CALayer before dismissing the VC? Note: If I declare layer as weak, the crash does not occur, but neither does the layer display onscreen.
> -Carl
>
>
> _______________________________________________
>
> Cocoa-dev mailing list (email@hidden)
>
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
--
David Duncan
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden