一个关于UITextView的奇葩问题 :-[UITextField textInputView]: message sent to deallocated instance

在公司的项目中,发现了一个奇葩问题,只要一点击输入框,系统过一段时间会崩溃.
在这个界面我监听了UIKeyboardWillShowNotificationUIKeyboardWillHideNotification,并且在delloc方法中释放了通知.
调试时我发现这个界面的 监听到UIKeyboardWillShowNotification键盘即将弹出时,调用的方法会连续走两次,然后程序就会崩掉.系统打印-[UITextField textInputView]: message sent to deallocated instance 0x156d12720
奇葩问题...
在项目中,为了使弹出的键盘不遮挡输入框,我添加了一个分类.这个分类在键盘弹出的时候判断如果键盘遮挡输入框,会让控制器的view上移.

@implementation UITextField (autoAdjust)

- (void)setAutoAdjust: (BOOL)autoAdjust
{
    if (autoAdjust) {
        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(keyboardWillShow:) name: UIKeyboardWillShowNotification object: nil];
        [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(keyboardWillHide:) name: UIKeyboardWillHideNotification object: nil];
    } else {
        [[NSNotificationCenter defaultCenter] removeObserver: self];
    }
}

- (void)keyboardWillShow: (NSNotification *)notification
{
    if (self.isFirstResponder) {
        CGPoint relativePoint = [self convertPoint: CGPointZero toView: [UIApplication sharedApplication].keyWindow];
        
        CGFloat keyboardHeight = [notification.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue].size.height;
        CGFloat actualHeight = CGRectGetHeight(self.frame) + relativePoint.y + keyboardHeight;
        CGFloat overstep = actualHeight - CGRectGetHeight([UIScreen mainScreen].bounds) + 5;
        if (overstep > 0) {
            CGFloat duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
            CGRect frame = [UIScreen mainScreen].bounds;
            frame.origin.y -= overstep + 10;
            [UIView animateWithDuration: duration delay: 0 options: UIViewAnimationOptionCurveLinear animations: ^{
                [UIApplication sharedApplication].keyWindow.frame = frame;
            } completion: nil];
        }
    }
}

- (void)keyboardWillHide: (NSNotification *)notification
{
    if (self.isFirstResponder) {
        CGFloat duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
        CGRect frame = [UIScreen mainScreen].bounds;
        [UIView animateWithDuration: duration delay: 0 options: UIViewAnimationOptionCurveLinear animations: ^{
            [UIApplication sharedApplication].keyWindow.frame = frame;
        } completion: nil];
    }
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver: self];
}

@end

结果查询了以后发现,就是这个分类出现了问题.解决的方法是不使用这个分类而在控制器中专门写代码控制view的移动.
这个问题的奇葩之处在于即便不使用,而且在代码中即使没有import这个分类,程序依然会报错.
引以为鉴,引以为鉴.

推荐阅读更多精彩内容