I have the following navigation flow in my app:
View controller A is embedded in a navigation controller.
A presents B modally.
Right before user dismisses B, the navigation controller's view controllers are set to: [A, C]
After B is dismissed, C is on screen.
Here's how the view controllers are set from B:
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let rootViewController = appDelegate.window!.rootViewController as! RootNavigationController
let Ccontroller = UIViewController()
var newControllers = rootViewController.viewControllers
newControllers.append(Ccontroller)
rootViewController.viewControllers = newControllers
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.dismissViewControllerAnimated(true, completion: nil)
})
A zombie is detected after pushes the back button on controller C. The crash is inconsistent. Sometimes I go through the navigation flow once, other times I go through the steps 15 times before receiving a crash.
I've looked through all the questions related to calling functions on deallocated objects and zombies, but most pertained to retain/release in Objective-C. I'm looking for a Swift solution.
The most common crash log:
*** -[CALayer retain]: message sent to deallocated instance 0x14b7d8880
A couple other crash logs our testers have found, which I believe are related to the same zombie issue.
Thread : Crashed: com.apple.main-thread
0 libobjc.A.dylib 0x180a780b0 objc_retain + 16
1 UIKit 0x186617c88 -[UIImageView isAnimating] + 132
2 UIKit 0x186605630 -[UIImageView stopAnimating] + 112
3 UIKit 0x186605334 -[UIImageView dealloc] + 64
4 libobjc.A.dylib 0x180a5eb54 object_cxxDestructFromClass(objc_object*, objc_class*) + 148
5 libobjc.A.dylib 0x180a6a040 objc_destructInstance + 92
6 libobjc.A.dylib 0x180a6a0a0 object_dispose + 28
7 UIKit 0x1869bae80 -[UIResponder dealloc] + 140
8 UIKit 0x186604ce8 -[UIView dealloc] + 1436
9 UIKit 0x18677fee0 -[UIControl dealloc] + 72
10 UIKit 0x18677ffe8 -[UIButton dealloc] + 100
11 UIKit 0x186a59474 -[UITouch .cxx_destruct] + 136
12 libobjc.A.dylib 0x180a5eb54 object_cxxDestructFromClass(objc_object*, objc_class*) + 148
13 libobjc.A.dylib 0x180a6a040 objc_destructInstance + 92
14 libobjc.A.dylib 0x180a6a0a0 object_dispose + 28
15 UIKit 0x186643388 -[UITouch dealloc] + 72
16 CoreFoundation 0x18142e384 __CFBasicHashDrain + 276
17 CoreFoundation 0x1812e2bdc CFDictionaryRemoveAllValues + 352
18 UIKit 0x186a51310 -[UITouchesEvent _setHIDEvent:] + 136
19 UIKit 0x186606dd8 _UIApplicationHandleEventQueue + 3984
20 CoreFoundation 0x1813b0538 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
21 CoreFoundation 0x1813affcc __CFRunLoopDoSources0 + 540
22 CoreFoundation 0x1813adccc __CFRunLoopRun + 724
23 CoreFoundation 0x1812d9670 CFRunLoopRunSpecific + 384
24 GraphicsServices 0x182bb0088 GSEventRunModal + 180
25 UIKit 0x186671ec4 UIApplicationMain + 204
26 Slide 0x100062a0c main (AppDelegate.swift:14)
27 libdispatch.dylib 0x180e768b8 (Missing)
_
Thread : Crashed: com.apple.main-thread
0 QuartzCore 0x24bfe690 CA::Layer::model_layer(CA::Transaction*) + 51
1 QuartzCore 0x24bfe64d -[CALayer modelLayer] + 32
2 QuartzCore 0x24bfe64d -[CALayer modelLayer] + 32
3 QuartzCore 0x24bfe4e9 -[CALayer animationForKey:] + 56
4 UIKit 0x26b0fbb5 -[UIImageView isAnimating] + 136
5 UIKit 0x26afdee3 -[UIImageView stopAnimating] + 102
6 UIKit 0x26afdc33 -[UIImageView dealloc] + 66
7 libobjc.A.dylib 0x22169f55 object_cxxDestructFromClass(objc_object*, objc_class*) + 116
8 libobjc.A.dylib 0x22173e47 objc_destructInstance + 34
9 libobjc.A.dylib 0x22173e6b object_dispose + 14
10 UIKit 0x26e99ccd -[UIResponder dealloc] + 128
11 UIKit 0x26afd635 -[UIView dealloc] + 1428
12 UIKit 0x26c7368d -[UIControl dealloc] + 64
13 UIKit 0x26c73789 -[UIButton dealloc] + 96
14 UIKit 0x26f2c2ab -[UITouch .cxx_destruct] + 126
15 libobjc.A.dylib 0x22169f55 object_cxxDestructFromClass(objc_object*, objc_class*) + 116
16 libobjc.A.dylib 0x22173e47 objc_destructInstance + 34
17 libobjc.A.dylib 0x22173e6b object_dispose + 14
18 UIKit 0x26b3ae99 -[UITouch dealloc] + 64
19 libobjc.A.dylib 0x22184f67 objc_object::sidetable_release(bool) + 150
20 CoreFoundation 0x229f0058 __CFBasicHashDrain + 336
21 CoreFoundation 0x228e1aa5 CFDictionaryRemoveAllValues + 276
22 UIKit 0x26f264a5 -[UITouchesEvent _setHIDEvent:] + 120
23 UIKit 0x26aff2ef _UIApplicationHandleEventQueue + 3366
24 CoreFoundation 0x2298768f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 14
25 CoreFoundation 0x2298727d __CFRunLoopDoSources0 + 452
26 CoreFoundation 0x229855eb __CFRunLoopRun + 794
27 CoreFoundation 0x228d8bf9 CFRunLoopRunSpecific + 520
28 CoreFoundation 0x228d89e5 CFRunLoopRunInMode + 108
29 GraphicsServices 0x23b24ac9 GSEventRunModal + 160
30 UIKit 0x26b68ba1 UIApplicationMain + 144
31 Slide 0xccfbc main (AppDelegate.swift:14)
32 libdispatch.dylib 0x22587873 (Missing)
How would you go about determining what code is causing this?
Normally this crash occurs when your ViewController is deallocated. Best practice to avoid this crash is make your ViewController as a property. Write getter method for it.
@property (nonatomic, strong) ViewController *aViewController;
(ViewController*)aViewController{
if(_aViewController == nil){
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle: nil];
_aViewController = (aViewController*)[mainStoryboard
instantiateViewControllerWithIdentifier: @"ViewControllerIdentifier"];
}
return aViewController;
}
- (IBAction)pushViewController{
[self.navigationController pushViewController:self.aViewController animated:YES];
}
Avoid making instances of your ViewController in your navigation method. Just make a single reference and use it again and again. It might be possible while making new references again and again in your navigation method, your previous viewcontroller instance got deallocated.