Инициализировать свойство 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, отличный от тех, которые я упомянул выше, которые на самом деле не являются идеальными решениями.


person Edward Lim    schedule 16.09.2017    source источник


Ответы (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) }
}
person Anders    schedule 16.09.2017
comment
Сладкий! Спасибо за это подробное объяснение! :) - person Edward Lim; 16.09.2017