Ios 视图/视图控制器层次结构和定位问题
我有一个问题,我尝试用两种方法来解决。两者都在一定程度上起作用,但最终都失败了。我们将非常感谢您对其中任何一位的帮助。此外,欢迎采用任何其他工作方法 这是需要完成的任务: 我有一个输入组件。为了简单起见,假设它只包含文本字段和发送按钮。它是一个视图控制器。“发送”按钮是另一个作为子视图控制器嵌入的视图控制器。然后,输入组件作为子视图控制器本身嵌入到某个更高级别的容器中。 这是无法改变的,我们必须视之为理所当然。 输入控制器应该足够聪明,能够在其文本字段成为第一响应者时在键盘上方显示自己 因此,第一种方法是将输入的组件Ios 视图/视图控制器层次结构和定位问题,ios,swift,ipad,layout,uitextfield,Ios,Swift,Ipad,Layout,Uitextfield,我有一个问题,我尝试用两种方法来解决。两者都在一定程度上起作用,但最终都失败了。我们将非常感谢您对其中任何一位的帮助。此外,欢迎采用任何其他工作方法 这是需要完成的任务: 我有一个输入组件。为了简单起见,假设它只包含文本字段和发送按钮。它是一个视图控制器。“发送”按钮是另一个作为子视图控制器嵌入的视图控制器。然后,输入组件作为子视图控制器本身嵌入到某个更高级别的容器中。 这是无法改变的,我们必须视之为理所当然。 输入控制器应该足够聪明,能够在其文本字段成为第一响应者时在键盘上方显示自己 因此,第
contentView
添加为文本字段的inputAccessoryView
func textFieldDidBeginEditing(_ textField: UITextField) {
// do some staff
// This needs to be done, because in above-keyboard position the input component has another layout compared to when it's inactive
contentView.layoutIfNeeded()
// This is the actual adding itself to be displayed above the keyboard
inputField.inputAccessoryView = contentView
}
guard let keyWindow = UIApplication.shared.keyWindow else { return }
contentViewBottomConstraint.constant = viewModel.bottomOffsetForInputField
NSLayoutConstraint.deactivate(originalContentViewConstraints)
contentViewToKeyboardLeadingConstraint = contentView.leadingAnchor.constraint(equalTo: keyWindow.leadingAnchor)
contentViewToKeyboardLeadingConstraint?.isActive = true
contentViewToKeyboardTrailingConstraint = contentView.trailingAnchor.constraint(equalTo: keyWindow.trailingAnchor)
contentViewToKeyboardTrailingConstraint?.isActive = true
据我所知,更多的工作人员在幕后工作,包括添加和删除子视图控制器。
然后,当用户点击返回按钮或发送按钮时,执行以下代码:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
这触发了
func textFieldDidEndEditing(_ textField: UITextField) {
// We add contentView back where it was before and reset constraints
view.addSubview(contentView)
contentView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
contentView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
contentView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
这段代码真是太棒了。唯一的问题是视图控制器层次结构似乎已损坏(输入组件不再显示在视图调试器中,但文本字段和按钮在屏幕上,因此我对此没有意见)
然后我找到了角落里的箱子。当用户通过点击屏幕上的任意位置来解除键盘时,或者当用户激活另一个文本字段时,不会调用textfieldReturn
,而是调用textfieldEndediting
因此,contentView
将从inputAccessoryView
中删除,但它不会出现在以前的位置
调试显示其超级视图
最终为nil
,这使我得出结论,即使我将其添加为视图的
子视图,iOS在某个点上也会删除它。
如果我在view.addSubview(contentView)
之前添加contentView.removeFromSuperview()
,则应用程序会被此错误消息压碎
线程1:异常:“子视图
控制器:UICompatibilityInputViewController:0x7fa13b2a3c00应
具有父视图控制器:(null)但实际为父视图控制器
is:UIInputWindowController:0x7fa136045000“
我不明白我的代码是如何犯下这种错误的,所以我可能做了一些从苹果的角度看我不应该做的事情
这就是我尝试第二种方法的原因。
这次我不使用inputAccessoryView
执行任何操作。相反,我只是修改了contentView
的底部约束,以便在显示键盘时向上移动:
func textFieldDidBeginEditing(_ textField: UITextField) {
contentViewBottomConstraint.constant = // whatever the keyboard's height is
UIView.animate(withDuration: viewModel.animationDurationForInputField,
delay: 0,
options: .curveEaseOut, animations: { [weak self] in
self?.view.layoutIfNeeded()
})
}
隐藏
func textFieldDidEndEditing(_ textField: UITextField) {
contentViewBottomConstraint.constant = 0
UIView.animate(withDuration: viewModel.animationDurationForInputField,
delay: 0,
options: .curveEaseOut, animations: { [weak self] in
self?.view.layoutIfNeeded()
})
}
这就像一种魅力,实际上这应该是正确的方法,而不会混淆视图控制器的inputAccessoryView
和子-父关系
但是,当该输入组件嵌入主/细节控制器的细节部分时,问题就开始了。在iPad上,细节部分占据了屏幕的一半左右。输入组件的宽度也是如此。当键盘显示时,输入组件被向上推,但其宽度保持不变——屏幕的一半
为了使其全屏显示,我获取了对顶部窗口的引用,取消激活了旧的前导和尾随约束,并添加了新的约束-在顶部窗口和contentView
之间
func textFieldDidBeginEditing(_ textField: UITextField) {
// do some staff
// This needs to be done, because in above-keyboard position the input component has another layout compared to when it's inactive
contentView.layoutIfNeeded()
// This is the actual adding itself to be displayed above the keyboard
inputField.inputAccessoryView = contentView
}
guard let keyWindow = UIApplication.shared.keyWindow else { return }
contentViewBottomConstraint.constant = viewModel.bottomOffsetForInputField
NSLayoutConstraint.deactivate(originalContentViewConstraints)
contentViewToKeyboardLeadingConstraint = contentView.leadingAnchor.constraint(equalTo: keyWindow.leadingAnchor)
contentViewToKeyboardLeadingConstraint?.isActive = true
contentViewToKeyboardTrailingConstraint = contentView.trailingAnchor.constraint(equalTo: keyWindow.trailingAnchor)
contentViewToKeyboardTrailingConstraint?.isActive = true
它确实变成了全屏,只有一半是不可见的,因为它在主/细节的细节部分,所以它被主部分重叠。
我不能把它带到前面
我尝试将其作为子视图添加到窗口崩溃中,因为子/父关系被破坏
将子视图移动到前面-没有效果(很明显,但我必须尝试)
改变位置-无效
所以,目前我的想法已经没有了。
这是一个非常极端的情况,但我需要让它工作,因为它(主/细节)是应用程序中的实际布局
提前感谢您的帮助