如何在SwiftUI中设置文本框字符限制?

3

我正在使用SwiftUI 2版本进行应用程序开发。 我在SwiftUI中使用的textfield遇到了问题。 我不想再使用UITextField了,我想限制TextField中字符的数量。 我搜索了很多,找到了一些相关的答案,但这些答案对于SwiftUI 2版本不起作用。

class textBindingManager: ObservableObject{
    let characterLimit: Int
    @Published var phoneNumber = "" {
        didSet {
            if phoneNumber.count > characterLimit && oldValue.count <= characterLimit {
                phoneNumber = oldValue
            }            
        }
    }
    init(limit: Int = 10) {
        characterLimit = limit
    }    
}

struct ContentView: View {
    @ObservedObject var textBindingManager = TextBindingManager(limit: 5)        
    var body: some View {
        TextField("Placeholder", text: $textBindingManager.phoneNumber)
    }
}
3个回答

5
不需要在已发布的属性上使用didSet。您可以为TextField添加修改器,并将字符串值限制为其前缀限制到字符限制:
import SwiftUI

struct ContentView: View {
    @ObservedObject var textBindingManager = TextBindingManager(limit: 5)
    var body: some View {
        TextField("Placeholder", text: $textBindingManager.phoneNumber)
            .padding()
            .onChange(of: textBindingManager.phoneNumber, perform: editingChanged)
    }
    func editingChanged(_ value: String) {
        textBindingManager.phoneNumber = String(value.prefix(textBindingManager.characterLimit))
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

class TextBindingManager: ObservableObject {
    let characterLimit: Int
    @Published var phoneNumber = ""
    init(limit: Int = 10){
        characterLimit = limit
    }
}

1
谢谢 - 这个特别有用,因为我在其他SO问题中找到的大多数答案都不能防止用户注意到有限制,直到值被保存并重新加载。 - m1g

1
以下是最简单的方式。它将字符数限制为10个。
struct ContentView: View {
    @State var searchKey: String = ""
    
    var body: some View {
        TextField("Enter text", text: $searchKey)
            .onChange(of: searchKey) { newValue in
                if newValue.count > 10 {
                    self.searchKey = String(newValue.prefix(10))
                }
            }
    }
}

0

这个解决方案将所有内容都封装在一个新组件中。您可以轻松地将其调整为执行其他解析/模式检查。

struct ContentView : View {
    @State private var myTextValue: String = ""
    
    var body: some View {
        LimitedTextField(value: $myTextValue, charLimit: 2)
    }
}


struct LimitedTextField : View {
    @State private var enteredString: String = ""
    @Binding var underlyingString: String
    let charLimit : Int
    
    init(value: Binding<String>, charLimit: Int) {
        _underlyingString = value
        self.charLimit = charLimit
    }
    
    var body: some View {
        HStack {
            TextField("", text: $enteredString, onCommit: updateUnderlyingValue)
                .onAppear(perform: { updateEnteredString(newUnderlyingString: underlyingString) })
                .onChange(of: enteredString, perform: updateUndelyingString)
                .onChange(of: underlyingString, perform: updateEnteredString)
        }
    }
    
    func updateEnteredString(newUnderlyingString: String) {
        enteredString = String(newUnderlyingString.prefix(charLimit))
    }
    
    func updateUndelyingString(newEnteredString: String) {
        if newEnteredString.count > charLimit {
            self.enteredString = String(newEnteredString.prefix(charLimit))
            underlyingString = self.enteredString
        }
    }
    
    func updateUnderlyingValue() {
        underlyingString = enteredString
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接