我已经阅读了documentation,经历了他们精彩的游乐场示例,搜索了SO,并达到了google-fu的范围,但我不能为我的生活包裹我的头如何使用ReactiveSwift。
鉴于以下内容......
class SomeModel {
var mapType: MKMapType = .standard
var selectedAnnotation: MKAnnotation?
var annotations = [MKAnnotation]()
var enableRouteButton = false
// The rest of the implementation...
}
class SomeViewController: UIViewController {
let model: SomeModel
let mapView = MKMapView(frame: .zero) // It's position is set elsewhere
@IBOutlet var routeButton: UIBarButtonItem?
init(model: SomeModel) {
self.model = model
super.init(nibName: nil, bundle: nil)
}
// The rest of the implementation...
}
....如何使用ReactiveSwift使用SomeViewController
中的值初始化SomeModel
,然后只要SomeViewController
中的值发生变化,就会更新SomeModel
我之前从未使用过任何反应,但我读过的所有内容都让我相信这应该是可能的。 这让我发疯了。
我意识到ReactiveSwift比我在这个例子中想要实现的更多,但如果有人可以用它来帮助我开始,我将非常感激。我希望一旦我得到这部分,剩下的就是"点击"。
答案 0 :(得分:19)
首先,您需要在模型中使用MutableProperty
而不是普通类型。这样,您就可以观察到对它们的更改。
class Model {
let mapType = MutableProperty<MKMapType>(.standard)
let selectedAnnotation = MutableProperty<MKAnnotation?>(nil)
let annotations = MutableProperty<[MKAnnotation]>([])
let enableRouteButton = MutableProperty<Bool>(false)
}
在ViewController中,您可以绑定它们并观察那些必要的内容:
class SomeViewController: UIViewController {
let viewModel: Model
let mapView = MKMapView(frame: .zero) // It's position is set elsewhere
@IBOutlet var routeButton: UIBarButtonItem!
init(viewModel: Model) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
routeButton.reactive.isEnabled <~ viewModel.enableRouteButton
viewModel.mapType.producer.startWithValues { [weak self] mapType in
// Process new map type
}
// Rest of bindings
}
// The rest of the implementation...
}
请注意,MutableProperty
同时包含.signal
和.signalProducer
。
如果您立即需要MutableProperty
的当前值(例如初始设置),请使用.signalProducer
立即发送包含当前值以及任何更改的事件。
如果您只需要对将来的更改做出反应,请使用.signal
,它只会发送事件以供将来更改。
Reactive Cocoa 5.0 will add UIKit bindings您可以使用它直接将UI元素绑定到您的反应层,就像示例中使用routeButton
一样。