View set as inputAccessoryView throws exception when added back into normal view

745 views Asked by At

I have a text view, some decorations etc. in a view and I want that view to dock on keyboard, just like any other messaging app.

When I'm about to display my text view, here is how I attach my view to the keyboard:

-(BOOL)textViewShouldBeginEditing:(UITextView *)textView{
    UIView *inputView = self.textInputView; //connected at IB outlet from storyboard, also contains the text view itself.
    constraintsOfTextInputView = [self constraintsRelatedToView:inputView]; //to be able to add them again
    [[UIApplication sharedApplication].keyWindow addSubview:self.textInputView];
    textView.inputAccessoryView = inputView;
    editingTextView = textView;
    return YES;
}

And when dismissing:

//using notification hook for UIKeyboardWillHideNotification because
//textView[Will|Did]EndEditing is called too late

-(void)keyboardWillHide{
    if(editingTextView && constraintsOfTextInputView){
        editingTextView.inputAccessoryView = nil;
        [self.textInputView removeFromSuperview];
        [self.view addSubview:self.textInputView]; <--- EXCEPTION
        [self.view addConstraints:constraintsOfTextInputView];
        [self.view layoutIfNeeded];

        editingTextView = nil;
        constraintsOfTextInputView = nil;
    }
}

Even though I'm doing exactly the opposite of what I do when adding, I'm getting this exception:

*** Terminating app due to uncaught exception
'UIViewControllerHierarchyInconsistency', reason: 'child view controller:
<UICompatibilityInputViewController: 0x13307ba20> should have parent view
controller:<ULPostViewController: 0x1307a7c00> but actual parent is:
<UIInputWindowController: 0x12f0be200>'

How can I get rid of this problem? I'm on iOS 8 (and don't support older versions).

UPDATE: I've created a git repository demonstrating the problem:

https://github.com/can16358p/CPInputAccessoryTest

2

There are 2 answers

7
Christian Schnorr On BEST ANSWER

You are abusing the inputView for something that it's not. The input view should be used for views the user an input data with, the input accessory view something you may want to extend that with. But its supposed be something like a keyboard.

Your text view is NOT part of that. It is the view the user is inputting data into. Decide if you want the view as an input view or in the main view hierarchy, but don't move it around before the two.

Your real problem is that you want to move the text view when the keyboard appears in order to keep it visible. To do so, observe the keyboard notifications

UIKeyboardWillShowNotification
UIKeyboardDidShowNotification
UIKeyboardWillHideNotification
UIKeyboardDidHideNotification

and move your views around accordingly. You can adjust the view controller's view's bounds origin for example, to move everything up.

2
Christian Schnorr On

You can use the text view as an input accessory view of the entire view controller. See my pull request.

Except for the growing text view part, this is pretty much the behavior of the Messages app.