当我输入它收到的字符时,我想从键盘输入字符,但是当我按任意键时,它收到的最后一个字符没有避免特殊字符怎么办
func digitswithPointOnly(text: Binding<String>) -> some View {
self.keyboardType(.decimalPad)
.onChange(of: text.wrappedValue) { newValue in
var filtered = newValue.filter { "0123456789.".contains($0) } // Allow digits
// Check if the string contains more than one decimal point
let decimalCount = filtered.reduce(0) { $0 + ($1 == "." ? 1 : 0) }
if decimalCount > 1 {
// Remove the last entered decimal point if more than one exists
filtered.removeLast()
} else if let index = filtered.firstIndex(of: ".") {
// Allow only two digits after the decimal point
let fractionalPart = filtered[filtered.index(after: index)...]
if fractionalPart.count > 2 {
// Remove digits after the second decimal place
let endIndex = filtered.index(index, offsetBy: 2)
filtered = String(filtered.prefix(upTo: endIndex))
}
}
text.wrappedValue = filtered
}
}
}
我在我的文本字段中使用此扩展
这是我的代码
let measurement = Measurement(measurement: index.id, value: newValue)
if !modifiedMeasurements.contains(measurement) {
modifiedMeasurements.append(measurement)
}}),prompt: Text(index.desc))
.digitswithPointOnly(text: Binding<String>(
get: { userMeasurements[index.id].stringValue },
set: { newValue in
userMeasurements[index.id] = JSON(newValue)
let measurement = Measurement(measurement: index.id, value: newValue)}))```
你可以这样做:
struct ContentView: View {
@State private var text: String = ""
var body: some View {
VStack {
TextField("placeholder", text: $text)
.keyboardType(.numbersAndPunctuation)
.padding(60)
}
.padding()
.onChange(of: text, initial: false) { oldValue, newValue in
let filtered = filter(text)
if newValue != filtered {
self.text = filtered
}
}
}
private func filter(_ text: String) -> String {
let allowedCharacters = "0123456789" + (Locale().decimalSeparator ?? ",")
return text.filter { allowedCharacters.contains($0) }
}
}
但是,仍有一些注意事项:
onChange
作为 @State 变量的技术解决方案,其中闭包更改原始值可能会导致无限循环 - 所以,我不推荐它。