#swift #swiftui #combine
#swift #swiftui #объединить
Вопрос:
У меня вопрос о быстром объединении. Допустим, у меня есть ObservableObject
с несколькими свойствами, подобными этому:
class AppState: ObservableObject{
static let shared = AppState()
@Published var a: Object?
@Published var b: Object?
@Published var c = [Object]()
}
Я знаю, что могу получать уведомления, если один объект изменяется таким образом:
myCancellable = AppState.shared.$a.sink { a in
//Object 'a' changed
}
Но есть ли способ просмотреть несколько свойств и отреагировать, если какое-либо из них изменится?
Что-то вроде:
myCancellable = AppState.shared.[$a, $b, $c].sink { a, b, c in
//Objects 'a', 'b', or 'c' changed
}
Ответ №1:
Возможным вариантом является наблюдение за любыми опубликованными изменениями всего объекта, например
myCancellable = AppState.shared
.objectWillChange.sink {
// react here
}
Ответ №2:
Предполагая, что a
, b
, и c
являются одним и тем же типом (на что мне указал Аспери, их нет в примере, поскольку c
это массив), вы можете использовать Publishers.MergeMany
:
myCancellable = Publishers.MergeMany([$a,$b,$c]).sink { newValue in
}
Существуют также более конкретные версии этой функции для заданного количества аргументов. Например, в вашем случае вы могли бы использовать Publishers.Merge3
Часто в примерах, которые я видел в Интернете, вы увидите Publishers.MergeMany
followed by collect()
, который собирает результаты от всех издателей, прежде чем двигаться дальше, публикуя результаты в виде массива. Однако из вашего вопроса не похоже, что это будет соответствовать вашим потребностям, поскольку вы хотите получать уведомление каждый раз, когда изменяется отдельный элемент.
Комментарии:
1. MergeMany предназначен для одного типа, но
c
является массивом в начальном вопросе темы, поэтому он не будет компилироваться.2. Ах, хорошая мысль. Пропустил эту деталь. Отредактированный пост, чтобы отразить это.
Ответ №3:
Спасибо за отличные ответы. Еще одна идея, на которую я наткнулся, заключалась в том, чтобы просто хранить мои объекты в a struct
и наблюдать за этим.
struct Stuff{
var a: Object?
var b: Object?
var c = [Object]()
}
Затем в моем AppState
классе:
class AppState: ObservableObject{
static let shared = AppState()
@Published var stuff: Stuff!
}
Затем в издателе:
myCancellable = AppState.shared.$stuff.sink { stuff in
print(stuff.a)
print(stuff.b)
print(stuff.c)
}
Мне нравится этот подход, поскольку я не хочу наблюдать за всем, что может измениться в AppState
классе (что, вероятно, указывает на то, что я должен разбить его на более мелкие части). Похоже, пока это работает хорошо.