在覆盖 firstResponder 中调用 resignFirstResponder 不起作用
Posted
技术标签:
【中文标题】在覆盖 firstResponder 中调用 resignFirstResponder 不起作用【英文标题】:Calling resignFirstResponder doesn't work within overrides firstResponder 【发布时间】:2016-01-25 04:57:35 【问题描述】:如何使用 UIResponder 聚焦激活的 UITextField?
代码如下:
// customTextField.swift
import UIKit
class customTextField: UITextField
override func becomeFirstResponder() -> Bool
if self.tag == 1
self.borderStyle = .Line
self.superview?.viewWithTag(2)?.resignFirstResponder()
self.superview?.viewWithTag(3)?.resignFirstResponder()
else if self.tag == 2
self.borderStyle = .Line
self.superview?.viewWithTag(1)?.resignFirstResponder()
self.superview?.viewWithTag(3)?.resignFirstResponder()
else
self.borderStyle = .Line
self.superview?.viewWithTag(1)?.resignFirstResponder()
self.superview?.viewWithTag(2)?.resignFirstResponder()
return true
override func resignFirstResponder() -> Bool
print("This is called")
self.borderStyle = .None
super.resignFirstResponder()
return true
我想通过 View 的标签检查哪个文本字段是 firstResponder。然后如果其他 TextField 不应该被 resignFirstResponder 关注。
但是,当我在视图中触摸 textField 时,甚至不会调用 becomefirstResponder 代码块中的 resignFirstResponder
。
【问题讨论】:
为何如此关注resignFirstResponder
?不是简单地成为第一响应者就辞去前响应者的职务吗?
感谢您的建议。我如何推荐前响应者?
查看下面的答案:它响应 Calling resignFirstResponder doesn't work
【参考方案1】:
不要破坏超类:传递消息
在覆盖系统消息的过程中,例如becomeFirstResponder
,您可能会无意中禁用父类。最安全、无操作的becomeFirstResponder
是这样的:
override func becomeFirstResponder() -> Bool
return super.becomeFirstResponder()
省略super.becomeFirstResponder()
会影响UITextField
。
也让原始逻辑(何时成为或不成为响应者)顺其自然。始终响应 true
或 false
会更改父类的行为,这可能会产生不良和不幸的副作用。
override func becomeFirstResponder() -> Bool
let becomeFirstResponder = super.becomeFirstResponder()
// Do stuff
return becomeFirstResponder
不要复制操作系统
无需跟踪当前响应者。
让操作系统通知您谁是响应者:否则,当屏幕键盘在没有点击新字段的情况下被关闭时,尝试进行跟踪实际上可能无法正常工作,并且必然会中断。相反,请以相同的方式收听resignFirstResponder
:
override func resignFirstResponder() -> Bool
return super.resignFirstResponder()
更少的代码,更多的灵活性
将两个规则放在一起,并使用.RoundedRect
和.Line
进行显式重绘(.None
无效),您的整个CustomTextField
可能如下所示:
class CustomTextField: UITextField
override func becomeFirstResponder() -> Bool
let becomeFirstResponder = super.becomeFirstResponder()
if becomeFirstResponder
self.borderStyle = .line
return becomeFirstResponder
override func resignFirstResponder() -> Bool
let resignFirstResponder = super.resignFirstResponder()
if resignFirstResponder
self.borderStyle = .roundedRect
return resignFirstResponder
请注意,如果 super.becomeFirstResponder()
或 super.resignFirstResponder()
未成功,不会采取任何措施。
演示
► 在GitHub 上查找此解决方案,在Swift Recipes 上查找更多详细信息。
【讨论】:
谢谢你。顺便说一句,我失败了。 Xcode 显示warning: could not load any Objective-C class information. This will significantly reduce the quality of type information available.
再次感谢您的帮助。我想我找到了我的项目不像你的那样工作的原因。在我的故事板中,我通过使用堆栈视图将每个标签和每个文本字段绑定在一起。然后我创建了三个堆栈视图。每个文本字段都在每个堆栈视图中。所以我认为在这种情况下你的代码不起作用。
这是我的项目的link。
将self.borderStyle = .None
替换为self.borderStyle = .RoundedRect
。
您可能需要调整布局约束以使单元格的高度保持不变。 .None
有一个奇怪的行为,但 .RoundedRect
有效。以上是关于在覆盖 firstResponder 中调用 resignFirstResponder 不起作用的主要内容,如果未能解决你的问题,请参考以下文章
在 ModalView 中丢失 firstResponder
在 Cocoa Mac OSX 中设置 FirstResponder 的问题
防止 UITextField 在更改 firstResponder 时取值
通过包含另一个 firstResponder(一个 UITextView)来创建一个 firstResponder UIView