【问题标题】:View set as inputAccessoryView throws exception when added back into normal view视图设置为 inputAccessoryView 在添加回普通视图时抛出异常
【发布时间】:2026-02-11 23:40:01
【问题描述】:

我在一个视图中有一个文本视图、一些装饰等,我希望该视图停靠在键盘上,就像任何其他消息传递应用程序一样。

当我要显示我的文本视图时,下面是我将视图附加到键盘的方法:

-(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;
}

当解雇时:

//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;
    }
}

即使我的操作与添加时的操作完全相反,我还是遇到了这个异常:

*** 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>'

我怎样才能摆脱这个问题?我使用的是 iOS 8(不支持旧版本)。

更新:我创建了一个 git 存储库来演示问题:

https://github.com/can16358p/CPInputAccessoryTest

【问题讨论】:

  • inputAccessoryView 无法添加到任何其他视图。除了将其设置为 inputAccessoryView 之外,为什么还要将其作为子视图添加到窗口中?
  • @rmaddy 因为如果我不这样做,它就不会显示。
  • @CanPoyrazoğlu UIKit 应该负责显示您的输入视图。
  • @ChristianSchnorr 但事实并非如此。如果我不将它添加到窗口中,它就会在编辑开始时消失。
  • @CanPoyrazoğlu 你能在某处上传一个示例项目吗?这是不可能的。

标签: ios ios8 uikeyboard inputaccessoryview


【解决方案1】:

您正在滥用inputView 来获取并非如此的东西。输入视图应该用于查看用户输入数据,输入附件视图是您可能想要扩展的东西。但它应该是键盘之类的东西。

您的文本视图不是其中的一部分。它是用户输入数据的视图。决定是否要将视图作为输入视图或在主视图层次结构中,但不要在两者之前移动它。

您真正的问题是您想在键盘出现时移动文本视图以使其可见。为此,请观察键盘通知

UIKeyboardWillShowNotification
UIKeyboardDidShowNotification
UIKeyboardWillHideNotification
UIKeyboardDidHideNotification

并相应地移动您的视图。例如,您可以调整视图控制器的视图边界原点,以向上移动所有内容。

【讨论】:

  • 不,您的建议实际上是我试图避免的事情。我正在努力实现这里的目标:derpturkey.com/uitextfield-docked-like-ios-messenger
  • 我无法让它工作。无论我尝试什么,我都无法摆脱这个错误。 //我所说的“它”是指我自己的项目基于那个。
  • 它显然没有用,我又回到了这个次优的解决方案。但是,我使用键盘的框架更改而不是将/确实显示/隐藏。
  • 由您决定收听哪些通知。我更喜欢显示/隐藏的,因为它们告诉我是否可以忽略框架键。
  • 顺便说一句,我试图摆脱这种方法的原因是真正将自定义视图“停靠”在键盘顶部,就像 FB Messenger 一样。我不知道他们是怎么做到的,但是当通过垂直平移交互地解除键盘时,它感觉真正停靠并且仍然平滑地连接到键盘。使用框架方法,我得到了一个非常接近的近似值,但它仍然不完美。
【解决方案2】:

您可以将文本视图用作整个视图控制器的输入附件视图。见my pull request

除了不断增长的文本视图部分,这几乎是 Messages 应用程序的行为。

【讨论】:

  • 我明白了。顺便说一句,我查看了您的拉取请求,我认为您已经删除了情节提要文件,但是当我尝试运行它时,它要求提供情节提要文件并崩溃。
  • 很奇怪,它对我来说并没有崩溃。现在应该修好了。