2013-12-05

[CALayer isKindOfClass:]: message sent to deallocated instance -- Get this error when using UINavigationController.

This is a tough one to debug, and I did not find many examples out there on solving this.

I was getting this error when manipulating my Navigation Controller stack via pushViewController. Here are the recreation steps:

  1. Due to user action, ViewControllerSubclassA instance X gets pushed to Navigation Controller stack.
  2. Due to user action, instance X pops itself from stack.
  3. Due to user action, ViewControllerSubclassA instance Y gets pushed to Navigation Controller stack.
  4. Crash happens!

There are going to be a thousand different reasons out there for this to occur, but I wanted to document my particular one in order to help.

I narrowed things down to which view by testing the app. I noticed that the crash only happened after I had tapped in a text field owned by ViewControllerSubclassA. Was a reference to a UITextField owned by a view controller still hanging around after the view controller was popped from the navigation controller stack? I added a debug line to find out.

2013-12-05 10:20:19.504 MyApp[82746:70b] -[MATypeAViewController viewDidLoad] [Line 50] CALayer of textField = CALayer: 0xefe5dd0
2013-12-05 10:20:27.373 MyApp[82746:70b] *** -[CALayer isKindOfClass:]: message sent to deallocated instance 0xefe5dd0

Yep, it sure was.

Removing this UITextFieldDelegate protocol method from my view controller solved the problem.

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
    if ([textField.text length] == MATextFieldIllegalLength)
    {
        return NO;
    }
    return YES;
}

What I guess was happening was that at times, NO was returned from this method, but the view controller popped itself from the stack anyway. This left a reference somewhere to the UITextField even though it got deallocated when its view controller went away.

2 comments: