Инициализация свойства RAC ReactiveSwift, которое имеет несколько зависимостей?
Я довольно новичок в использовании ReactiveSwift и ReactiveCocoa, и мне кажется, что я столкнулся с проблемой, касающейся правильного способа инициализации свойства, имеющего зависимости.
Например, в следующем коде я пытаюсь инициализировать свойство, но получаю ожидаемую ошибку компилятора. Мой вопрос заключается в том, как / каков "правильный" способ сделать это.
class SomeViewModel {
// illustration purposes, in reality the property (dependency) we will observe will change over time
let dependency = Property(value: true)
let dependency2 = Property(value: "dependency2")
let dependency3 = Property(value: 12345)
let weightLabel: Property<String>
// private(set) var weightLabel: Property<String>!
// using private(set) var weightLabel: Property<String>! works,
// however this changes the meaning behind using let, because we could
// reinitalize weightLabel again which is not similar to using a let so not a good alternative
// let weightLabel: Property<String> = Property(value: "")
// another solution that will work but will result in a wrong value
// upon initalization then, changed into the "correct value" thus, i
// am discrading this as well
init() {
weightLabel = dependency.map {
// compiler error, 'self' captured by closure before all members were initalized.
// My question is if there is a way to handle this scenario properly
if $0 && self.dependency2.value == "dependency2" && self.dependency3.value == 12345 {
return ""
}
return ""
}
}
}
Так что, как вы могли заметить выше в комментариях, мне интересно, есть ли способ справиться с этим сценарием с помощью ReactiveSwift, отличным от тех, которые я упомянул выше, и которые не являются действительно идеальными решениями.
1 ответ
Инструмент, который соответствует сценарию, combineLatest
, который предоставляет комбинированную версию всех этих свойств (потоков) всякий раз, когда любое из них было обновлено.
weightLabel = Property.combineLatest(dependency, dependency2, dependency3)
.map { d1, d2, d3 in
return "Hello World! \(d1) \(d2) \(d3)"
}
Что касается ошибки компилятора, проблема в том, что вы захватываете / ссылаетесь на self
в закрытии до того, как каждое сохраненное свойство было инициализировано. В зависимости от намерения, вы можете использовать список захвата, чтобы напрямую захватывать интересующие вас значения и объекты без self
,
let title: String
let action: () -> Void
init() {
title = "Hello World!"
// `action` has not been initialised when `self` is
// being captured.
action = { print(self.title) }
// ✅ Capture `title` directly. Now the compiler is happy.
action = { [title] in print(title) }
}