我有一个重点文本框。
@FocusState private var focusedField: Field?
TextField("0", value: $price, format: .currency(code: "USD").locale(Locale(identifier: "en_US")))
.keyboardType(.numbersAndPunctuation)
.multilineTextAlignment(.trailing)
.focused($focusedField, equals: field)
还有一个按钮
Button("Tap") { price = 200 }
但是,如果文本字段获得焦点,则不能使用按钮重写文本字段中的值。文本字段需要不聚焦才能做到这一点。
当我重写代码时:
Button("Tap") {
focusedField = nil
price = 200
}
它会关闭键盘,但仍然不会重写文本字段中的值。只有在键盘关闭后,如果我再次点击按钮,它才会重写文本字段中的值。
我怎样才能完成这项工作?
在 SwiftUI 中,TextField 在获得焦点时不会更新其绑定。强制更新的一种方法是利用 TextField 的 onChange 事件。
首先,为之前的价格值创建一个状态:
@State private var previousPrice: String = ""
然后,将一个
onChange
事件添加到您的TextField
以更新previousPrice
状态:
TextField("0", value: $price, format: .currency(code: "USD").locale(Locale(identifier: "en_US")))
.keyboardType(.numbersAndPunctuation)
.multilineTextAlignment(.trailing)
.focused($focusedField, equals: field)
.onChange(of: price, perform: { value in
previousPrice = value
})
现在,在您的按钮操作中,将
price
值与 previousPrice
进行比较。如果它们相同,则意味着 TextField 尚未更新其绑定。因此,您可以先将 price
设置为空字符串,然后在短暂的延迟后将其设置回所需的值。
Button("Tap") {
if price == previousPrice {
price = ""
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
price = 200
}
} else {
price = 200
}
}
这将确保 TextField 中的值即使在获得焦点时也会更新。
根据我的评论,您可以尝试这种替代方法, 使用
String
,如示例代码所示。
因为在
TextField
中,如果值是字符串,文本字段会不断更新此值……对于非字符串类型,它会在用户提交编辑时更新值,例如通过按 Return 键。
对我来说效果很好。就是多了几行代码,但至少有 没有等待 0.1 秒的广告。
enum Field: Hashable {
case price
}
struct ContentView: View {
var body: some View {
TestView()
}
}
struct TestView: View {
@State private var txt = ""
@State private var price = 0.0
@FocusState private var focusedField: Field?
func asCurrency(_ str: String) -> String {
if let value = Double(str) {
let frmt = NumberFormatter()
frmt.numberStyle = .currency
frmt.maximumFractionDigits = 2
frmt.minimumFractionDigits = 2
frmt.locale = Locale(identifier: "en_US")
if let str = frmt.string(for: value) {
return str
}
}
return ""
}
var body: some View {
TextField(asCurrency("0"), text: Binding(
get: { asCurrency(txt) },
set: {
if let d = Double($0) {
price = d
txt = $0
}
}))
.keyboardType(.numbersAndPunctuation)
.multilineTextAlignment(.trailing)
.focused($focusedField, equals: .price)
Button("Tap") {
focusedField = nil
price = 200.0
txt = String(price)
}
}
}