iosobjective-cnszombie

UITextField textInputView message sent to deallocated instance


I have crashes which occur when I tap on UITextField. I have two controllers, let's say A and B. When I show controller B modally in controller A, and tap on UITextField everything is OK. Then I dismiss controller B, and present it again. This time when I click on UITextField crash occurs. When I enabled NSZombie in my scheme, there is message of crash - -[UITextField textInputView]: message sent to deallocated instance.

I have no UITextFieldDelegate set on UITextField. When I tried to debug with Instruments -> Zombies, there is no source code (Unavailable) when I double click some release/retain history line.

My scheme's Build Configuration is Debug. Xcode version is 7.2.1. Crashes occur only on iOS 8. iOS 9 is fine.

PS: When I try re-symbolicate app, I see that there is one missing System Frameworks dyld. Then I press Locate button and open dsym file of my debug app, but error occurs with message "The specified path didn't locate a dSYM for any of the selected libraries."

UPDATE 1:

A controller:

#import <UIKit/UIKit.h>

@interface A : UIViewController
@end

#import "A.h"
#import "RoundedButton.h"

@interface A ()
@property (weak, nonatomic) IBOutlet RoundedButton *signInButton;
@end

@implementation A

- (void)viewDidLoad {
    [super viewDidLoad];

    [self configUI];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault animated:YES];
    [self.navigationController setNavigationBarHidden:YES animated:YES];
}

- (UIStatusBarStyle)preferredStatusBarStyle {
    return UIStatusBarStyleDefault;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Segue

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"signIn"]) {

    }
}

#pragma mark - Config UI

- (void)configUI {
    // setup ui    
}

- (void)dealloc {
    NSLog(@"%@ deallocated", NSStringFromClass([self class]));
}

@end

B controller:

#import <UIKit/UIKit.h>

@interface B : UIViewController
@end

#import "B.h"
#import "SKFormTextField.h"
#import "RoundedButton.h"

@interface B () 
@property (weak, nonatomic) IBOutlet UITextField *textField;
@property (weak, nonatomic) IBOutlet RoundedButton *signInButton;
@end

@implementation B {
    SKAlertView *alertView;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    [self configUI];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
}

#pragma mark - Actions

- (IBAction)cancelSignIn:(id)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}

#pragma mark - Config UI

- (void)configUI {
    self.navigationController.navigationBarHidden = YES;

    self.textField.secureTextEntry = true;
    self.textField.autocorrectionType = UITextAutocorrectionTypeNo;
}

- (void)dealloc {
    NSLog(@"%@ deallocated", NSStringFromClass([self class]));
}

@end

UPDATE 2:

When I call UITextField, like self.textField.text = @"Hello, World!";, there is no crash. Only when I pan/touch UITextField or call [self.textField becomeFirstResponder]; it crashes.


Solution

  • Finally, I found reason of my crashes. I have UITextField extension called UITextField (AutoSuggestion) where I called dealloc method to remove own observers.

    Code sample:

    /* .h file */
    #import <UIKit/UIKit.h>
    // some protocol
    @interface UITextField (AutoSuggestion)
    // some properties and methods
    @end
    
    /* .m file */
    #import "UITextField+AutoSuggestion.h"
    #import <objc/runtime.h>
    @implementation UITextField (AutoSuggestion)
    - (void)observeTextFieldChanges {
        self.layer.masksToBounds = NO;
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(toggleAutoSuggestion:) name:UITextFieldTextDidChangeNotification object:self];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(hideAutoSuggestion) name:UITextFieldTextDidEndEditingNotification object:self];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(getKeyboardHeight:)
                                                     name:UIKeyboardDidShowNotification
                                                   object:nil];
    }
    
    - (void)dealloc {
        [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidChangeNotification object:nil];
        [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidEndEditingNotification object:nil];
        [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
    }
    // other methods
    @end
    

    After I removed dealloc method crashes disappeared. Therefore I decided to find new way to implement autosuggestion feature.

    The interesting thing is that I didn't import header file in code anywhere, but crashes occurred.