#swift #combine
#swift #объединить
Вопрос:
Я пытаюсь заставить один объект прослушивать изменения в свойстве другого объекта. У меня это работает, как показано ниже, но я бы предпочел, чтобы наблюдающий объект ничего не знал о модели, только о свойстве.
class Model : ObservableObject{
@Published var items: [Int] = []
}
class ObjectUsingItems{
var itemObserver: AnyCancellable?
var items: [Int] = []
func observeItems(model: Model){
itemObserver = model.$items
.sink{ newItems in
self.items = newItems
print("New Items")
}
}
}
На данный момент я начинаю наблюдать за model.items следующим образом — что работает:
let model = Model()
let itemUser = ObjectUsingItems()
itemUser.observeItems(model: model)
model.items.append(1) // itemUser sees changes
К сожалению, я не могу понять, что требуется в качестве параметра для метода observeItems, чтобы он работал, ничего не зная о модели — вот так:
class ObjectUsingItems{
var itemObserver: AnyCancellable?
var items: [Int] = []
func observeItems(propertyToObserve: WhatGoesHere?){
itemObserver = propertyToObserve
.sink{ newItems in
// etc.
}
}
}
А затем назовите это следующим образом:
itemUser.observeItems(XXX: model.$items)
Кто-нибудь может объяснить, что мне нужно сделать? Спасибо!
Ответ №1:
Вы можете просто принять publisher в качестве параметра, если вам все равно, откуда берется значение.
В вашем очень конкретном случае это может быть:
func observeItems(propertyToObserve: Published<[Int]>.Publisher) {
itemObserver = propertyToObserve
.sink { self.items = $0 }
}
Но это может быть слишком ограничительным — почему только этот конкретный издатель? В принципе, вас не должно волновать, кто является издателем — все, что вас волнует, это выходное значение и тип ошибки. Вы можете сделать его универсальным для любого издателя, при условии, что его вывод [Int]
и сбой Never
(как у @Published
одного):
func observeItems<P: Publisher>(propertyToObserve: P)
where P.Output == [Int], P.Failure == Never {
itemObserver = propertyToObserve
.sink { self.items = $0 }
}
Использование было бы примерно таким:
let model = Model()
let itemUser = ObjectUsingItems()
itemUser.observeItems(propertyToObserve: model.$items)
Комментарии:
1. Большое спасибо новому разработчику — работает отлично, и я бы никогда этого не понял.