我可以在这里提供两件事。一个快速而肮脏的解决方案(我希望)和一个建议(或者你可以称之为我感到惊讶)。
肮脏的解决方案:实现这样的东西
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
self.shouldCloseKeyboard = false
return true
}
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
return self.shouldCloseKeyboard
}
@IBAction func inputDone(_ sender: AnyObject) {
if self.inputField.isFirstResponder {
self.shouldCloseKeyboard = true
self.inputField.resignFirstResponder()
}
}
inputDone: 将连接到您的“发布”按钮,并且显然还包含您发布所需的任何其他内容(或者您将其放入 textFieldShouldEndEditing 如果并且在您关闭它之前,即完成输入) . shouldCloseKeyboard 是一个 Bool 变量,它被初始化为 false,但随后使用,如您在此处看到的那样。显然inputField 是您的文本字段(不是整个附件视图!),整个类都符合UITextFieldDelegate,并且文本字段的实例通过接口生成器(或其他方式)设置为delegate。
这应该如你所愿。我在一个示例项目中进行了尝试,尽管我没有使用像您这样的工具栏(见下文)或将所有内容放入表格中。我只是做了一个简单的 webview,下面有一个输入和一个关闭东西的按钮。一旦文本字段成为第一响应者,即键盘启动,我可以在 web 视图中单击、点击链接等,并且键盘并没有消失。单击按钮时,它正确关闭(当时我没有打扰什么是第一响应者)。
现在让我感到惊讶的是:起初我认为简单地使用工具栏作为inputAccessoryView 让它在键盘上移动是一个不错的技巧。但是,经过进一步思考,我得出的结论是,我不会这样做(而是在显示键盘时手动向上移动视图以及其他任何内容。您可能也必须这样做,以确保没有什么重要的被键盘或附件视图遮挡)。原因是附属视图不应该已经在其他地方的视图层次结构中。事实上,当我在我的演示项目中以简单的方式快速尝试它时(我将按钮和文本字段嵌入到 UIView 中,为此定义了一个出口,然后在代码中将其设置为 inputAccessoryView,尝试各个地方)应用程序崩溃了。这是合理的,因为文本字段本身是容器的子视图,这将是附件,但同时是视图控制器主视图的子视图......我很惊讶你设法克服了这一切。
简而言之,这种方法似乎很麻烦。我理解输入附件视图的方式,它们更多地用于附加视图,而不是用于已经显示在屏幕上的控件(因此已经是视图层次结构的一部分)。在另一个项目中,我专门通过简单地伪造它来避免弄乱它:我有一个单独的视图作为附件加载,看起来就像它“关联”的控件。一旦显示了这个假视图,我将第一响应者切换到它(嗯,切换到它的一个子视图,一个文本字段,所以键盘保持不变)并且我的用户可以编辑掉。按下完成按钮后,我将输入复制到“原始”文本字段,一切都很好。
因此,从长远来看,我建议您(或任何人)重新考虑将现有视图作为附件进行处理,而是在需要时选择“常规”视图转换,并将附件视图作为“附加助手”。
更新:
好的,我上面描述的(在“快速而肮脏”的解决方案中)假设您只希望 一种方式 退出编辑,即防止 任何其他成为第一响应者,并且只有在按下“完成”后才让它失去第一响应者。
关于 webView 它完成了同样的事情。尝试only 阻止 webView 成为第一响应者时的问题是如何识别导致文本字段失去第一响应者状态的原因。我认为您的“hacky”方法指向了正确的方向,但是由于您不应该覆盖扩展(iirc)中的方法,因此我建议在这种情况下将 UIWebView 子类化。然后,您还可以给它一个属性来打开和关闭该行为(即,如果文本字段成为第一响应者/开始编辑您将其打开,一旦它丢失,您将其关闭)。这对于子类来说应该足够了:
class MyWebView: UIWebView {
public var shouldNotBecomeFirstResponder = false;
override public var canBecomeFirstResponder: Bool {
if self.shouldNotBecomeFirstResponder {
return false
} else {
return super.canBecomeFirstResponder
}
}
}
(我确保如果未设置新的Bool,则会模仿原始行为,这将导致该类在所有其他情况下的行为与 webView 完全相同。不过,我没有在您的设置中进行测试。 )
显然应该在所有适当的地方设置shouldNotBecomeFirstResponder。例如,我想你可以通过监听键盘(dis)出现通知来做到这一点。
通常,可能还有其他不需要子类的方法。除了我上面的第一个建议之外,您也许可以使用手势识别器来确定是否必须设置 shouldCloseKeyboard,但这可能需要更多的工作并且导致难以阅读/维护代码。可能很难弄清楚首先调用了什么,确定是否点击了 webView 的逻辑(因此必须设置 shouldCloseKeyboard 在它实际上成为第一响应者!)或其他东西(在在这种情况下必须以某种方式取消设置)。
所以我#d 使用子类,即使子类几乎没有向 webView 添加任何内容。 :)