Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 视图/视图控制器层次结构和定位问题_Ios_Swift_Ipad_Layout_Uitextfield - Fatal编程技术网

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
它确实变成了全屏,只有一半是不可见的,因为它在主/细节的细节部分,所以它被主部分重叠。 我不能把它带到前面

我尝试将其作为子视图添加到窗口崩溃中,因为子/父关系被破坏

将子视图移动到前面-没有效果(很明显,但我必须尝试)

改变位置-无效

所以,目前我的想法已经没有了。 这是一个非常极端的情况,但我需要让它工作,因为它(主/细节)是应用程序中的实际布局

提前感谢您的帮助