SwiftUI 自定义文本字段未获取更新值

SwiftUI custom textfield not getting updated value

我想创建一个带有一些输入按钮的自定义文本字段,单击这些按钮时文本字段应相应地更新值。

我有多个选项可以在 InputView 中设置值,因此如果我编辑 InputView 并且单击任何按钮,该按钮应该更新值。

这是我的代码


@main
struct AmountApp: App {
    var body: some Scene {
        WindowGroup {
            InputView()
        }
    }
}
struct InputView: View {
    @State var value: Double = 0.00
    var body: some View {
        VStack {
            Text("Amount")
            TextInput(value: $value).padding(.horizontal)
            HStack(alignment: .center, spacing: 16) {
                Button { value = 20 } label: { Text("20") }
                Button { value = 30 } label: { Text("30") }
                Button { value = 40 } label: { Text("40") }
            }
            
            Button { print(value) } label: {
                Text("Print")
                    .padding(8)
                    .foregroundColor(.red)
            }
        }
    }
}


struct TextInput: UIViewRepresentable {
    @Binding var value: Double
    
    func makeCoordinator() -> Coordinator { Coordinator(self) }
    
    func updateUIView(_ uiView: UITextField, context: Context) { }
    
    func makeUIView(context: Context) ->  UITextField {
        let textfield = UITextField()
        textfield.placeholder = "Enter amount"
        textfield.text = "\(value)"
        textfield.keyboardType = .decimalPad
        textfield.setContentHuggingPriority(.defaultHigh, for: .vertical)
        textfield.setContentHuggingPriority(.defaultLow, for: .horizontal)
        textfield.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
        return textfield
    }
    
    class Coordinator: NSObject, UITextFieldDelegate {
        var parent: TextInput
        init(_ textField: TextInput) { self.parent = textField }
    }
}

非常感谢您的帮助,~美好的一天。!!

如果您不实施UITextFieldDelegate 方法来接收用户输入(SwiftUI Custom TextField with UIViewRepresentable Issue with ObservableObject and pushed View),绑定值将不会更新

当您从 SwiftUI 端更改值时,您的 UIViewRepresentable 需要处理 updateUIView 中的更改(将新值传递给 UITextField)

另外记得设置textfield.delegate = context.coordinator以便接收事件。

struct TextInput: UIViewRepresentable {
    @Binding var value: Double
    
    func makeCoordinator() -> Coordinator { Coordinator(self) }
    
    // for handling swiftui-side modification to the binding (your buttons)
    func updateUIView(_ uiView: UITextField, context: Context) { 
        uiView.text = value
    }
    
    func makeUIView(context: Context) ->  UITextField {
        let textfield = UITextField()
        textfield.placeholder = "Enter amount"
        textfield.text = "\(value)"
        textfield.keyboardType = .decimalPad
        textfield.setContentHuggingPriority(.defaultHigh, for: .vertical)
        textfield.setContentHuggingPriority(.defaultLow, for: .horizontal)
        textfield.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
        textfield.delegate = context.coordinator // set the delegate
        return textfield
    }
    
    class Coordinator: NSObject, UITextFieldDelegate {
        var parent: TextInput
        init(_ textField: TextInput) { self.parent = textField }
        func textFieldDidEndEditing(_ textField: UITextField) {
            if let text = textField.text {
                parent.value = Double(text) ?? 0
            } else {
                parent.value = 0
            }
        }
    }
}