如何解决Swift 中的 UITextField – 输入
我现在正在 Swift 中编写自定义 UITextField,遇到以下情况:
class MyField: UITextField {
open override var text: String? {
didSet {
// some logic that normalizes the text
}
}
private func setup() { //called on init
addTarget(self,action: #selector(textEditingChanged(_:)),for: .editingChanged)
}
@objc func textEditingChanged(_ sender: UITextField) {
}
}
现在,在对此进行测试时,我观察到,当用户键入内容时,会调用 textEditingChanged
,但不会调用 text.didSet
。就此而言,text.willSet
也不是。但是,在 textEditingChanged
中,文本字段的文本已更新为新值。
谁能解释一下这里发生了什么? Swift 是故意绕过 setter 的吗?我应该如何知道何时/是否调用 setter,UIKit 中是否有任何逻辑?
解决方法
UITextField
的 text 属性仅供外部使用,当您键入 UIKit
时会在内部处理更新。无法真正说出幕后发生了什么,因为我们无法访问 UIKit
实现,但问题的一个可能答案是 UITextField
正在使用另一个内部变量来存储文本属性.当您获取 text 属性时,您实际上是在获取该内部值,而在设置它时,您也在设置该内部值。当然在引擎盖下它有点复杂,但它可能看起来像这样(SampleUITextField
代表UITextField
):
// This how the UITextField implementation may look like
class SampleUITextField {
private var internalText: String = ""
var text: String {
get {
internalText
} set {
internalText = newValue
}
}
// This method is just to demonstrate that when you update the internalText didSet is not called
func updateInternalTextWith(text: String) {
internalText = text
}
}
当你子类化它时,它看起来像:
class YourTextField: SampleUITextField {
override var text: String {
didSet {
print("DidSet called")
}
}
}
现在,当您直接设置文本属性时,会调用 didSet
,因为 text
值会更新。你可以检查一下:
let someClass = YourTextField()
someClass.text = "Some new text"
// didSet is called
但是现在当您调用 updateInternalTextWith
时,不会调用 didSet
:
let someClass = YourTextField()
someClass.updateInternalTextWith(text: "new text")
// didSet is not called
那是因为您没有直接更新文本值,而只是更新内部文本属性。键入时会调用类似的方法来更新 UITextField
的内部文本变量,这就是在您的情况下未调用 didSet
的原因。
因此,当我们希望在文本属性更改时收到通知时,仅覆盖 text
变量是不够的,我们需要使用 delegate(UITextFieldDelegate
) 方法或通知 ({ {1}}) 以捕捉实际更改。
您想在 UITextField 上执行哪种格式设置?
这不应该由 ViewModel(或管理包含此文本字段的视图的业务逻辑的任何模型)来代替吗?
此外,您不应该使用 didSet
来执行更改,它主要用于允许您响应更改,而不是链接另一个更改。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。