Это очень конкретный и длинный вопрос, но я не достаточно умен, чтобы понять это самостоятельно.
Я был очень заинтригован этим YouTube-видео от raywenderlich.com, которое использует метод "бокса" для наблюдения значения.
Их Box
выглядит так:
class Box<T> {
typealias Listener = T -> Void
var listener: Listener?
var value: T {
didSet {
listener?(value)
}
init(_ value: T) {
self.value = value
}
func bind(listener: Listener?) {
self.listener = listener
listener?(value)
}
}
Очевидно, что только «1011» * один слушатель разрешен для «ящика».
let bindable:Box<String> = Box("Some text")
bindable.bind { (text) in
//This will only be called once (from initial setup)
}
bindable.bind { (text) in
// - because this listener has replaced it. This one will be called when value changes.
}
Всякий раз, когда устанавливается такая привязка, предыдущие привязки удаляются, поскольку Box
заменяет listener
новым слушателем.
Мне нужно иметь возможность наблюдать одно и то же значение из разных мест. Я переделал Box
так:
class Box<T> {
typealias Listener = (T) -> Void
var listeners:[Listener?] = []
var value:T{
didSet{
listeners.forEach({$0?(value)})
}
}
init(_ value:T){
self.value = value
}
func bind(listener:Listener?){
self.listeners.append(listener)
listener?(value)
}
}
Однако - это также доставляет мне неприятности, очевидно .. Есть места, где я хочу новое связывание, чтобы удалить старое связывание. Например, если я наблюдаю значение в объекте из многократно используемого UITableViewCell
, оно будет связано несколько раз при прокрутке. Теперь мне нужен контролируемый способ избавиться от определенных привязок.
Я попытался решить эту проблему, добавив эту функцию в Box
:
func freshBind(listener:Listener?){
self.listeners.removeAll()
self.bind(listener)
}
Это сработало, теперь я мог использовать freshBind({})
всякий раз, когда хотел удалить старых слушателей, но это не совсем то, чего я хочу. Я должен был бы использовать это при наблюдении значения от UITableViewCell
s, но мне также нужно наблюдать то же значение из другого места. Как только камера использовалась повторно, я удалил старых наблюдателей , а также других наблюдателей, которые мне были нужны.
Теперь я уверен, что мне нужен способ сохранить одноразовый предмет там, где я впоследствии захочу его утилизировать.
Я не достаточно умен, чтобы решить это самостоятельно, поэтому мне нужна помощь.
Я едва использовал некоторые из сред реактивного программирования (например, ReactiveCocoa), и теперь я понимаю, почему их подписки возвращают Disposable
объекты, которые я должен сохранять и распоряжаться ими, когда мне нужно. Мне нужен этот функционал.
Я хочу вот что: func bind(listener:Listener?)->Disposable{}
Я планировал создать класс с именем Disposable
, который содержал (необязательный) слушатель, и превратить listeners:[Listener?]
в listeners:[Disposable]
, но у меня возникли проблемы с <T>
..
Cannot convert value of type 'Box<String?>.Disposable' to expected argument type 'Box<Any>.Disposable'
Какие-нибудь умные предложения?