#swiftui #combine
#swiftui #объединить
Вопрос:
Я пытаюсь выяснить, как связать @Binding
переданное в пользовательское представление @Published
с моделью этого представления. По сути, я пытаюсь создать текстовое поле только для повторного использования. Я использую приведенный ниже код, который работает для установки целочисленного значения в текстовое поле, но чего я не могу понять, так это как обновить привязку при изменении текста.
private class IntegerTextFieldValue: ObservableObject {
@Published var value = "" {
didSet {
let numbersOnly = value.filter { $0.isNumber }
if value != numbersOnly {
value = numbersOnly
}
}
}
}
struct IntegerTextField: View {
@Binding var value: Int?
@StateObject private var fieldValue = IntegerTextFieldValue()
var placeholder = ""
var body: some View {
TextField(placeholder, text: $fieldValue.value)
.keyboardType(.numberPad)
.onAppear {
if let value = value {
fieldValue.value = "(value)"
}
}
}
}
Ответ №1:
Если я вас правильно понял
.onChange (of: fieldValue.value) { vl in
value = vl
}
этот модификатор обновляет привязку value
до $fieldValue.value
Комментарии:
1.
onChange
принимает значение, а не привязку. Однако ваш ответ здесь, по сути, дал мне то, что мне нужно, используя.onChange(of: fieldValue.value) { value = Int($0) }
Ответ №2:
Вот измененный код для демонстрации возможного подхода (протестирован с Xcode 12.1 / iOS 14.1):
private class IntegerTextFieldValue: ObservableObject {
@Published var value = "" {
didSet {
let numbersOnly = value.filter { $0.isNumber }
if value != numbersOnly {
value = numbersOnly
}
if let number = Int(value) {
numberValue = number
}
}
}
@Published var numberValue: Int = 0
}
struct IntegerTextField: View {
@Binding var value: Int?
@StateObject private var fieldValue = IntegerTextFieldValue()
var placeholder = ""
var body: some View {
TextField(placeholder, text: $fieldValue.value)
.keyboardType(.numberPad)
.onAppear {
if let value = value {
fieldValue.value = "(value)"
}
}
.onChange(of: fieldValue.numberValue) {
if $0 != self.value {
self.value = $0
}
}
}
}