#swift #xcode #swiftui #combine
#swift #xcode #swiftui #объединить
Вопрос:
У меня есть представление с моделью представления, и действия в этом представлении могут изменить модель представления. Чтобы иметь возможность разбивать логику на части, которые можно использовать повторно, у меня есть часть представления как собственное представление с привязкой @ к значениям, которые ему нужны. Теперь я хочу иметь возможность выполнять некоторую логику, основанную на изменениях значений, не обязательно только просматривать изменения. Как я могу это сделать? Если бы это было обычное свойство, я бы внедрил didSet, но это ни к чему меня не привело. Я хотел использовать Combine to и рассматривать @Binding как издателя, но я также не смог найти способ сделать это. Предложения?
Вот код:
class ViewModel: ObservableObject {
@Published var counter: Int = 0
}
struct Greeter: View {
@Binding var counter: Int {
didSet {
// this isn't printed....
print("Did set -> (counter)")
}
}
init(counter: Binding<Int>) {
self._counter = counter
// ...so how about setting up a subscription to the @Binding counter above here?
}
var body: some View {
Text("Hello, world #(counter)!")
.padding()
}
}
struct ContentView: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
VStack {
Greeter(counter: $viewModel.counter)
Button("Go!") {
viewModel.counter = 1
}
}
}
}
Итак, я хочу сохранить структуру, в которой данные находятся в ViewModel, и что только ее части передаются в подвиде. И это в подвиде (приветствие) Я хочу иметь возможность что-то сделать (скажем, напечатать значение, как в didSet)
Ответ №1:
Вот возможный подход. Протестировано с Xcode 11.4 / iOS 13.4 (SwiftUI 1.0 )
struct Greeter: View {
@Binding var counter: Int
var body: some View {
Text("Hello, world #(counter)!")
.padding()
.onReceive(Just(counter)) { // << subscribe
print(">> greeter: ($0)") // << use !!
}
}
}
Примечание для SwiftUI 2.0 : вы можете использовать .onChange(of: counter) {
вместо этого (который на самом деле является встроенной заменой выше)
Комментарии:
1. Спасибо за предложение. onChange имеет дополнительное преимущество в том, что реагирует только при изменении значения, в отличие от onReceive, который также запускается при загрузке представления
2. мне потребовалась вечность, чтобы найти это для поддержки ios13, идеальная замена onChange, спасибо 🙂
3. Он просто вызывается при каждом обновлении представления, не так ли?
4. Да, это стек в цикле
5. Для меня
.onReceive(Just(binding))
работает, но.onChange(of: binding)
нет.