[英]SwiftUI TextField won't change its contents under weird corner case with Binding<String> computed property
我在 SwiftUI 主體中有一個 TextField。 我已經通過一個中間綁定將它綁定到一個@State var,它讓我可以獲取和設置一個計算值......
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)
// [...]
我正在使用中間綁定,以便我可以將字符串轉換為始終為僅包含字母 AZ 的大寫格式(如我的 .regularExpression 所引用)。 (我正在嘗試使 TextField 僅在每次按鍵時顯示格式正確的股票符號)。
這有點管用。 我發現的問題是,如果我不兩次調用賦值(如圖 1 所示),TextField將開始顯示數字和字母(即使它不包含在 symbolToBeValidated 字符串中。我懷疑會發生這種情況,因為 SwiftUI 在內部根據 newValue 檢查 oldValue 並且因為它沒有在后台更改,所以它不會調用刷新來再次獲取內部值。我發現阻止這種情況的方法是包含一個額外的在 .replacingOccurences 調用之前賦值。
這會導致數字或符號在用戶鍵入時在屏幕上閃爍以顯示一個 blip,然后它會被 .replacingOccurences 調用正確刪除。
必須有一種更優雅的方式來做到這一點。 我使用了 Formatter 類類型並嘗試了這種替代方法,只是因為 Formatter 導致了類似的行為,即錯誤的字符在被刪除之前會在屏幕上閃爍。
如果有人知道在屏幕上顯示任何內容之前攔截它的方法,我將不勝感激。 這是非常挑剔的,但我只是在這里尋找正確的答案。
嘗試這個:
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())
這種方式還允許您重用和測試驗證代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.