当所有文本字段在 SwiftUI 中都有值时,如何动态更新屏幕上的标签?
How do I dynamically update labels on a screen when all text fields have values in SwiftUI?
我正在开发一款允许用户使用 2 个单独的文本字段输入投注赔率的应用程序。例如,假设用户想要的赔率是 3/1。用户需要在一个字段中输入 3,在另一个字段中输入 1。
我有 2 个状态变量:
- leftOddsVal
- 右赔率
这就是我将它们与 CustomTextField 一起使用的方式:
CustomTextfield(text: $leftOddsVal, placeHolder: "Enter text", keyboardType: .numberPad)
CustomTextfield(text: $rightOddsVal, placeHolder: "Enter text", keyboardType: .numberPad)
CustomTextfield(text: $state, placeHolder: "Enter text", keyboardType: .numberPad)
这是自定义文本字段的代码:
struct CustomTextfield: UIViewRepresentable {
@Binding var text : String
var placeHolder: String
var keyboardType: UIKeyboardType
final class Coordinator: NSObject {
var textField: CustomTextfield
init(_ textField: CustomTextfield) {
self.textField = textField
}
}
func makeCoordinator() -> DabbleTextfield.Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> UITextField {
let textField = UITextField()
textField.backgroundColor = .white
textField.placeholder = self.placeHolder
textField.keyboardType = self.keyboardType
return textField
}
func updateUIView(_ uiView: UITextField, context: Context) {
}
}
我要做什么:
我想获取每个字段的值,并编写一些逻辑来计算可以赢多少和输多少,然后更新屏幕上的一些文本标签。我希望 win/lose 标签在所有字段都有值后自动更新,而不是让用户在他们看到他们可能赢或输之前提交表单。
这些是标签的外观:
问题:
textFieldDidEndEditing 委托方法需要知道触发什么方法。这意味着,我需要修改 CustomTextField 以触发我的 viewModel 中将触发的方法。然后我可以触发win/lose计算方法。然而,我开始觉得,对于如此简单的事情来说,这需要做很多工作。看起来很乱
我无法直接在视图中访问文本字段值。如果我使用 SwiftUI 的 TextField 组件,这会很简单。但是,我正在使用包装在 UIRepresentable 结构中的 UIKit 的 UITextField 组件,如您在上面的代码中所见。
我试过的:
我有一个视图模型,我试图将其传递到 CustomtextField 中。
我只是这样声明我的环境变量:
struct CustomTextfield: UIViewRepresentable {
@EnvironmentObject var viewModel: EnvironmentObject<AnyObject>
@Binding var text : String
var placeHolder: String
var keyboardType: UIKeyboardType
我使用了 AnyObject,这样我就可以将传递给 CustomTextField 的任何模型作为正确的类型进行投射。我不想手动修改 CustomTextField 来满足我可能使用它的每个模型。
我现在这样使用 CustomTextField:
CustomTextfield(viewModel: betViewModel as! EnvironmentObject<BetViewModel>, value: $oddsLeftValue, placeHolder: "Enter text", keyboardType: .numberPad)
然后我将 TextField 的副本存储在我的 ViewModel 的一个变量中:
func makeUIView(context: Context) -> UITextField {
let textField = UITextField()
if let fieldValue = textField.text {
self.viewModel.textField = fieldValue
}
但我收到以下错误:
Type 'AnyObject' does not conform to protocol 'ObservableObject'
我也试过将绑定的文本值设置为文本字段的值,但这也没有用。
我希望有人能告诉我我做错了什么。我觉得我在兜圈子,而造成这种情况的原因是试图重用 UIRepresentable UIKit 组件。它似乎限制了我,这导致变通办法似乎对我想要实现的目标来说是一种矫枉过正。
我想要做的就是允许用户输入他们的赔率和赌注,并动态更新 win/lose 标签,而无需点击任何按钮。同时能够重用 CustomTextField。
期待您的建议。
提前致谢。
以下内容使您的自定义文本字段可操作...用于更新外部绑定,希望这是这么长的描述的目的。
测试 Xcode 11.4 / iOS 13.4
末尾的小 TestCustomTextfield
用于检查 CustomTextfield
中更改的更新标签。
struct CustomTextfield: UIViewRepresentable {
@Binding var text : String
var placeHolder: String
var keyboardType: UIKeyboardType
final class Coordinator: NSObject, UITextFieldDelegate {
var parent: CustomTextfield
init(_ parent: CustomTextfield) {
self.parent = parent
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
parent.text = textField.text ?? ""
return true
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> UITextField {
let textField = UITextField()
textField.backgroundColor = .white
textField.placeholder = self.placeHolder
textField.keyboardType = self.keyboardType
textField.setContentHuggingPriority(.required, for: .vertical)
textField.delegate = context.coordinator
return textField
}
func updateUIView(_ uiField: UITextField, context: Context) {
if let text = textField.text as NSString? {
parent.text = text.replacingCharacters(in: range, with: string)
} else {
parent.text = ""
}
}
}
struct TestCustomTextfield: View {
@State private var value = ""
var body: some View {
VStack {
Text("Label: \(value)")
CustomTextfield(text: $value, placeHolder: "Your value", keyboardType: .numberPad)
}
}
}
我正在开发一款允许用户使用 2 个单独的文本字段输入投注赔率的应用程序。例如,假设用户想要的赔率是 3/1。用户需要在一个字段中输入 3,在另一个字段中输入 1。
我有 2 个状态变量:
- leftOddsVal
- 右赔率
这就是我将它们与 CustomTextField 一起使用的方式:
CustomTextfield(text: $leftOddsVal, placeHolder: "Enter text", keyboardType: .numberPad)
CustomTextfield(text: $rightOddsVal, placeHolder: "Enter text", keyboardType: .numberPad)
CustomTextfield(text: $state, placeHolder: "Enter text", keyboardType: .numberPad)
这是自定义文本字段的代码:
struct CustomTextfield: UIViewRepresentable {
@Binding var text : String
var placeHolder: String
var keyboardType: UIKeyboardType
final class Coordinator: NSObject {
var textField: CustomTextfield
init(_ textField: CustomTextfield) {
self.textField = textField
}
}
func makeCoordinator() -> DabbleTextfield.Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> UITextField {
let textField = UITextField()
textField.backgroundColor = .white
textField.placeholder = self.placeHolder
textField.keyboardType = self.keyboardType
return textField
}
func updateUIView(_ uiView: UITextField, context: Context) {
}
}
我要做什么:
我想获取每个字段的值,并编写一些逻辑来计算可以赢多少和输多少,然后更新屏幕上的一些文本标签。我希望 win/lose 标签在所有字段都有值后自动更新,而不是让用户在他们看到他们可能赢或输之前提交表单。
这些是标签的外观:
问题:
textFieldDidEndEditing 委托方法需要知道触发什么方法。这意味着,我需要修改 CustomTextField 以触发我的 viewModel 中将触发的方法。然后我可以触发win/lose计算方法。然而,我开始觉得,对于如此简单的事情来说,这需要做很多工作。看起来很乱
我无法直接在视图中访问文本字段值。如果我使用 SwiftUI 的 TextField 组件,这会很简单。但是,我正在使用包装在 UIRepresentable 结构中的 UIKit 的 UITextField 组件,如您在上面的代码中所见。
我试过的:
我有一个视图模型,我试图将其传递到 CustomtextField 中。
我只是这样声明我的环境变量:
struct CustomTextfield: UIViewRepresentable {
@EnvironmentObject var viewModel: EnvironmentObject<AnyObject>
@Binding var text : String
var placeHolder: String
var keyboardType: UIKeyboardType
我使用了 AnyObject,这样我就可以将传递给 CustomTextField 的任何模型作为正确的类型进行投射。我不想手动修改 CustomTextField 来满足我可能使用它的每个模型。
我现在这样使用 CustomTextField:
CustomTextfield(viewModel: betViewModel as! EnvironmentObject<BetViewModel>, value: $oddsLeftValue, placeHolder: "Enter text", keyboardType: .numberPad)
然后我将 TextField 的副本存储在我的 ViewModel 的一个变量中:
func makeUIView(context: Context) -> UITextField {
let textField = UITextField()
if let fieldValue = textField.text {
self.viewModel.textField = fieldValue
}
但我收到以下错误:
Type 'AnyObject' does not conform to protocol 'ObservableObject'
我也试过将绑定的文本值设置为文本字段的值,但这也没有用。
我希望有人能告诉我我做错了什么。我觉得我在兜圈子,而造成这种情况的原因是试图重用 UIRepresentable UIKit 组件。它似乎限制了我,这导致变通办法似乎对我想要实现的目标来说是一种矫枉过正。
我想要做的就是允许用户输入他们的赔率和赌注,并动态更新 win/lose 标签,而无需点击任何按钮。同时能够重用 CustomTextField。
期待您的建议。 提前致谢。
以下内容使您的自定义文本字段可操作...用于更新外部绑定,希望这是这么长的描述的目的。
测试 Xcode 11.4 / iOS 13.4
末尾的小 TestCustomTextfield
用于检查 CustomTextfield
中更改的更新标签。
struct CustomTextfield: UIViewRepresentable {
@Binding var text : String
var placeHolder: String
var keyboardType: UIKeyboardType
final class Coordinator: NSObject, UITextFieldDelegate {
var parent: CustomTextfield
init(_ parent: CustomTextfield) {
self.parent = parent
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
parent.text = textField.text ?? ""
return true
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> UITextField {
let textField = UITextField()
textField.backgroundColor = .white
textField.placeholder = self.placeHolder
textField.keyboardType = self.keyboardType
textField.setContentHuggingPriority(.required, for: .vertical)
textField.delegate = context.coordinator
return textField
}
func updateUIView(_ uiField: UITextField, context: Context) {
if let text = textField.text as NSString? {
parent.text = text.replacingCharacters(in: range, with: string)
} else {
parent.text = ""
}
}
}
struct TestCustomTextfield: View {
@State private var value = ""
var body: some View {
VStack {
Text("Label: \(value)")
CustomTextfield(text: $value, placeHolder: "Your value", keyboardType: .numberPad)
}
}
}