У меня есть следующий SwiftUI View
(извлеченный и упрощенный код):
struct MyView<T : Hashable>: View {
private let selection: Binding<T?>?
init(selection: Binding<T?>) {
self.selection = selection
}
init() {
self.selection = nil
}
var body: some View {
VStack {
...
}
.onChange(of: selection) { newValue in <== ERROR
...
}
}
}
Я получаю следующую ошибку: Referencing instance method 'onChange(of:perform:)' on 'Optional' requires that 'Binding<T?>' conform to 'Equatable'
.
Как это можно решить?
Переключиться на использование оболочки
struct MyView<T : Hashable>: View {
@Binding var selection: T?
init(selection: Binding<T?>) {
self._selection = selection
}
init() {
//Dead end not recommended for use outside of Previews
//Will cause undesirable behavior by mimicking having a source of truth.
self._selection = .constant(nil)
}
var body: some View {
VStack {
Text("")
}
.onChange(of: selection) { newValue in //<== ERROR
//Do work here
}
}
}
https://developer.apple.com/documentation/swiftui/binding/constant(_:)
Вы также должны отметить, что Binding
по определению двустороннее соединение.
Зачем Binding
, если его изменения зайдут в тупик? Аналогичные результаты можно получить с...
struct MyView<T : Hashable>: View {
let selection: T?
var body: some View {
VStack {
Text("")
}.onAppear(){
//Do work here
}
}
}
private let selection: Binding<T?>?
«эквивалентен» (но не совсем) использованию оболочки и последующему доступу к $selection
.
Я никогда не вникал в причину, по которой SwiftUI требует обертки, а не только типы, но это связано с соответствием DynamicProperty
, wrappedValue
и projectedValue
. View
не будет знать, когда обновлять, если вы используете Binding<Type>
против @Binding
.
Нежелательное поведение с представлениями, которые предоставят пользователю UX, намекающий на то, что его действия влияют на что-то значимое, плюс есть другие ошибки, такие как дерганое поведение и неотзывчивый пользовательский интерфейс.
Спасибо, это сработало. В полном коде selection
нет тупика. Не могли бы вы объяснить, что вызвало мою ошибку и почему использование оболочки решает ее? Какое нежелательное поведение может произойти и что именно?
@meaning-matters Я добавил дополнительную информацию.
@lorem ipsum прав, много вопросов у людей, пытающихся передать значения с помощью
Binding<T>
... в этом нет необходимости, просто передайте значение через инициализацию или конструктор по умолчанию (если вы не реализовали ни одну инициализацию), эти представления все равно каждый раз разрушаются и реконструируются.