使用双值识别 SwiftUI TextField 中的更改
Recognize changes in SwiftUI TextField with double value
我正在使用 TextField 让用户为某物添加价格。为了防止用户将其他值添加为数字,我将键盘类型更改为 .decimalPad
.
stringValue
会根据每个字符更改的绑定进行正确更新。我现在的问题是,doubleValue
仅在用户按下回车键时才更新。不幸的是,小数点键盘没有回车键来提交输入。因此,当我尝试在不按 enter 键的情况下将值保存到我的核心数据对象时,将保存 0 而不是文本字段中的可见值(例如 17.12)。现在为了测试,我将使用另一种带有输入按钮的键盘类型,但对于生产,这需要以某种方式修复。
您知道如何解决这个问题吗?下面是显示问题的最小化示例代码。
struct ContentView: View {
@State private var doubleValue: Double = 0.0
@State private var stringValue = "Test"
private let numberFormatter: NumberFormatter = {
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .currency
return numberFormatter
}()
var body: some View {
Form {
TextField("", text: $stringValue)
.disableAutocorrection(true)
HStack {
Text("Price")
Spacer()
TextField("", value: $doubleValue, formatter: numberFormatter)
.fixedSize()
.keyboardType(.decimalPad)
}
// show live value changes
Text("\(stringValue)")
Text("Value: \(doubleValue)")
}
.padding()
}
func saveToCoreData() {
// save values into core data
}
}
我正在使用 Xcode 12.2 和 MacOS BigSur 11.0.1。
编辑属于asperis评论:
您共享的解决方案看起来不错,但正如您在屏幕截图中看到的那样,它的工作原理并不正确:
在使用值 0
进行初始设置后,我输入了 2
,然后输入了 3
。显示的值是 2.03
这确实不是我想要的。也许我可以加强你提示的方法。
我有类似的问题。这是我实施的解决方案,因为如果它不是字符串,则无法检测到键入的值。这个想法是将值作为字符串,然后在进一步处理该值之前将其转换为 Double。如果传递的是 Double 值,则需要先将其转换为 String,然后再将其绑定到 TextField。
struct SomeTextField: View {
@State var string: String = ""
@State var double: Double = 0.0
func save() {
double = Double(string)!
}
var body: some View {
VStack {
Text("String: \(string) Double: \(String(double))")
TextField("0.00", text: $string).keyboardType(.decimalPad)
Button(action: save) { Text("Save") }
}
}
在 iOS 15 上,您可以使用 TextField ("Hello", value: $someDoubleValue, formatter: <your NumberFormatter here>)
并且值传播良好。
在 iOS 14 上,使用格式化程序将 TextField
绑定到 Double
值似乎不起作用。
因此以下内容在 iOS 15 中工作正常,但在 iOS 14 中不起作用。
注意 double 值嵌套在这里,因为这是从我现在正在处理的内容中提取的代码片段。
public class MyViewModel: ObservableObject {
@Published var child: ChildObject
}
public class ChildObject: Identifiable, ObservableObject {
@Published var doubleValue: Double
}
public struct FancyPantsView: View {
@ObservedObject var viewModel: MyViewModel
public var body: some View {
VStack {
TextField ("Hello", value: $viewModel.child.doubleValue, formatter: amountFormatter)
.keyboardType(.decimalPad)
}
}
let amountFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.zeroSymbol = ""
return formatter
}()
}
我正在使用 TextField 让用户为某物添加价格。为了防止用户将其他值添加为数字,我将键盘类型更改为 .decimalPad
.
stringValue
会根据每个字符更改的绑定进行正确更新。我现在的问题是,doubleValue
仅在用户按下回车键时才更新。不幸的是,小数点键盘没有回车键来提交输入。因此,当我尝试在不按 enter 键的情况下将值保存到我的核心数据对象时,将保存 0 而不是文本字段中的可见值(例如 17.12)。现在为了测试,我将使用另一种带有输入按钮的键盘类型,但对于生产,这需要以某种方式修复。
您知道如何解决这个问题吗?下面是显示问题的最小化示例代码。
struct ContentView: View {
@State private var doubleValue: Double = 0.0
@State private var stringValue = "Test"
private let numberFormatter: NumberFormatter = {
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .currency
return numberFormatter
}()
var body: some View {
Form {
TextField("", text: $stringValue)
.disableAutocorrection(true)
HStack {
Text("Price")
Spacer()
TextField("", value: $doubleValue, formatter: numberFormatter)
.fixedSize()
.keyboardType(.decimalPad)
}
// show live value changes
Text("\(stringValue)")
Text("Value: \(doubleValue)")
}
.padding()
}
func saveToCoreData() {
// save values into core data
}
}
我正在使用 Xcode 12.2 和 MacOS BigSur 11.0.1。
编辑属于asperis评论:
您共享的解决方案看起来不错,但正如您在屏幕截图中看到的那样,它的工作原理并不正确:
在使用值 0
进行初始设置后,我输入了 2
,然后输入了 3
。显示的值是 2.03
这确实不是我想要的。也许我可以加强你提示的方法。
我有类似的问题。这是我实施的解决方案,因为如果它不是字符串,则无法检测到键入的值。这个想法是将值作为字符串,然后在进一步处理该值之前将其转换为 Double。如果传递的是 Double 值,则需要先将其转换为 String,然后再将其绑定到 TextField。
struct SomeTextField: View {
@State var string: String = ""
@State var double: Double = 0.0
func save() {
double = Double(string)!
}
var body: some View {
VStack {
Text("String: \(string) Double: \(String(double))")
TextField("0.00", text: $string).keyboardType(.decimalPad)
Button(action: save) { Text("Save") }
}
}
在 iOS 15 上,您可以使用 TextField ("Hello", value: $someDoubleValue, formatter: <your NumberFormatter here>)
并且值传播良好。
在 iOS 14 上,使用格式化程序将 TextField
绑定到 Double
值似乎不起作用。
因此以下内容在 iOS 15 中工作正常,但在 iOS 14 中不起作用。
注意 double 值嵌套在这里,因为这是从我现在正在处理的内容中提取的代码片段。
public class MyViewModel: ObservableObject {
@Published var child: ChildObject
}
public class ChildObject: Identifiable, ObservableObject {
@Published var doubleValue: Double
}
public struct FancyPantsView: View {
@ObservedObject var viewModel: MyViewModel
public var body: some View {
VStack {
TextField ("Hello", value: $viewModel.child.doubleValue, formatter: amountFormatter)
.keyboardType(.decimalPad)
}
}
let amountFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.zeroSymbol = ""
return formatter
}()
}