簡體   English   中英

SwiftUI TextField 不會在帶有 Binding 的奇怪的極端情況下更改其內容<String>計算屬性

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM