【问题标题】:Calling resignFirstResponder doesn't work within overrides firstResponder在覆盖 firstResponder 中调用 resignFirstResponder 不起作用
【发布时间】: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

标签: ios swift uitextfield uiresponder


【解决方案1】:

不要破坏超类:传递消息

在覆盖系统消息的过程中,例如becomeFirstResponder,您可能会无意中禁用父类。最安全、无操作的becomeFirstResponder 是这样的:

override func becomeFirstResponder() -> Bool {
    return super.becomeFirstResponder()
}

省略super.becomeFirstResponder() 会影响UITextField

也让原始逻辑(何时成为或不成为响应者)顺其自然。始终响应 truefalse 会更改父类的行为,这可能会产生不良和不幸的副作用。

    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 有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-24
  • 2014-04-03
  • 1970-01-01
  • 1970-01-01
  • 2019-01-31
  • 2020-02-14
相关资源
最近更新 更多