在Swift中的viewModel上没有调用ReactiveCocoa订阅块

时间:2014-08-30 19:13:53

标签: ios mvvm swift reactive-cocoa

我正在使用MVVM和ReactiveCocoa构建一个app来在viewModel和UI之间进行绑定,但是视图模型验证信号订阅块没有被调用。

我的视图模型非常简单和准确:

class ViewModel: RVMViewModel {
    var name: String = "" {
        willSet {
            println("New Value: \(newValue)")
        }
    }

   required init(){
       super.init()
       let signal = self.rac_valuesForKeyPath("name", observer: self)
       signal.subscribeNext {
           println("Subscribe block: \($0)")
       }
   }
}

在我的视图控制器中,我有以下绑定:

//observe ui and programatic changes
RACSignal.merge([self.nameField.racTextSignal(), self.nameField.rac_valuesForKeyPath("text", observer:self)]).subscribeNext({
     (next) -> Void in
     if let text = next as? String {
         self.viewModel.name = text
     }
})
RAC(self.nameField, "text") = self.viewModel.rac_valuesForKeyPath("name", observer: self)

根据我读到的here,我让RAC宏在swift中工作。

现在,在我的视图控制器中的视图绑定中,subscribeNext块被调用就好了。在我的viewModel中,在willSet中打印出新值。但是,当初始化属性时,我的init块中的信号上的订阅块仅被调用一次。这让我兴奋不已,任何人都有任何想法?

3 个答案:

答案 0 :(得分:2)

我在一堆实验后找到了解决方案。通过将信号直接分配给视图模型属性,每次值更改时都会调用subscribe块。

所以不要这样做:

RACSignal.merge([self.nameField.racTextSignal(), self.nameField.rac_valuesForKeyPath("text", observer:self)]).subscribeNext({
     (next) -> Void in
     if let text = next as? String {
         self.viewModel.name = text
     }    
})

我这样做了:

RAC(self.viewModel, "name") <~  RACSignal.merge([self.nameField.racTextSignal(),     
self.nameField.rac_valuesForKeyPath("text", observer:self)])

我使用this linkRAC<~在swift中工作。

答案 1 :(得分:1)

我还没有解决方案 - 我离笔记本电脑一直到晚上。但是,尝试在全局范围或实例变量中制作信号......如果这不起作用,请在单例上尝试将其作为您明确调用的方法...这些是更多测试但是如果你告诉我它是怎么回事我们可以一起解决这个问题。

答案 2 :(得分:0)

比接受的解决方案更好的解决方案是简单地将属性标记为动态:

dynamic var name: String = "" {
    willSet {
        println("New Value: \(newValue)")
    }
}

这使得Obj-C级别KVO通常仅对Swift属性禁用。