SwiftUI 文本字段不会在使用绑定计算属性的奇怪极端情况下更改其内容<String>



我在 SwiftUI 正文中有一个 TextField。我已通过中介绑定将其绑定到@State变量,这使我能够获取并设置计算值...

struct ExampleView: View {
@State var symbolToBeValidated: String = ""
var body: some View {
let binding = Binding<String> (get: {
return self.symbolToBeValidated
}, set: {
var newString = $0.uppercased()
self.symbolToBeValidated = newString // <- fig. 1: redundant assignment I wish I didn't have to put
newString = newString.replacingOccurrences(
of: #"[^A-Z]"#,
with: "",
options: .regularExpression
)
self.symbolToBeValidated = newString // <- fig. 2: the final, truly valid assignment
})
let form = Form {
Text("What symbol do you wish to analyze?")
TextField("ex.AAPL", text: binding)
// [...]

我正在使用中间绑定,以便我可以将字符串转换为始终仅包含字母 A-Z 的大写格式(由我的 .regularExpression 引用(。(我正在尝试使文本字段仅在每次按键时显示有效格式的股票代码(。

这在某种程度上有效。我发现的问题是,如果我不调用赋值两次(如图 1 所示(,TextField将开始显示数字和字母(即使它不包含在 symbolToBeValidate 字符串中。我怀疑发生这种情况是因为 SwiftUI 正在内部检查 oldValue 和 newValue,并且因为它在后台没有更改,所以它不会调用刷新来再次获取内部值。我发现阻止这种情况的方法是在 .replacingOccurrenceences 调用之前包含一个额外的赋值。

这会导致数字或符号在用户键入时在屏幕上闪烁,然后由 .replacingOccurrenceences 调用正确删除。

必须有一种更优雅的方式来做到这一点。我选择了格式化程序类类型并尝试了这种替代方法,只是因为格式化程序导致了类似的行为,即错误字符在被删除之前会在屏幕上闪烁。

如果有人知道在屏幕上显示任何内容之前拦截的方法,我将不胜感激。这是超级吹毛求疵,但我只是在这里寻找正确的答案。

试试这个:


extension Binding where Value == String {
public func validated() -> Self {
return .init(
get: { self.wrappedValue },
set: {
var newString = $0.uppercased()
newString = newString.replacingOccurrences(
of: #"[^A-Z]"#,
with: "",
options: .regularExpression
)
self.wrappedValue = newString
}
)
}
}
// ...
TextField("ex.AAPL", text: self.$symbolToBeValidated.validated())

这种方式还允许您重用和测试验证代码。

相关内容

最新更新