我开始使用ReactiveCocoa,我仍在努力解决一些基本概念:
init
)didFindCurrentPosition
被调用)viewDidLoad
在我的视图控制器中)viewDidLoad
)我的问题是:在完成第2步后,如果信号上没有发送其他事件,我的视图控制器不会收到通知。
我的视图控制器如何访问信号中的最后一个值? (即如何在步骤3中访问步骤2中发出的值?)
感谢您的帮助。
PS:ReactiveCocoa看起来像一个很棒的库,但我对文档的状态感到困惑。恕我直言,它不是很清楚,缺乏一些关于如何使用它的明确指南。
视图模型:
class MyViewModel: LocationManagerDelegate {
let locationManager: LocationManager
let geolocationDataProperty = MutableProperty<Geolocation?>(nil)
let geolocationData: Signal<Geolocation?, NoError>
init() {
geolocationData = geolocationDataProperty.signal
// Location Management
locationManager = LocationManager()
locationManager.delegate = self
locationManager.requestLocation()
}
// MARK: - LocationManagerDelegate
func didFindCurrentPosition(location: CLLocation) {
geolocationDataProperty.value = Geolocation(location: location)
}
}
视图控制器:
class MyViewController: UIViewController {
let viewModel = MyViewModel()
init() {
super.init(nibName: nil, bundle: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
viewModel.geolocationData
.observe(on: UIScheduler())
.observeValues { geolocation in
debugPrint("GOT GEOLOCATION")
}
}
}
答案 0 :(得分:4)
您已经拥有一个Property
来保存最新的值。而不是使用属性signal
使用producer
。这样当你启动producer
时,你将首先得到当前值(没有发送,你将得到零)。
比照。 the documentation:
可以从值getter获取属性的当前值。生产者getter返回一个信号生成器,它将发送属性的当前值,随后是所有随时间变化的。信号获取器返回一个信号,该信号将随时间发送所有变化,但不是初始值。
因此,关于问题中的代码,viewDidLoad
方法应该执行以下操作:
viewModel.geolocationDataProperty
.producer
.start(on: UIScheduler())
.startWithValues { geolocation in
debugPrint("GOT GEOLOCATION")
}
答案 1 :(得分:0)
可以使用&lt;〜运算符来设置来自任何类型的值的绑定,但是您可以按照以下方式开始修改代码并看到它工作正常,它更容易调试: - )
class MyViewModel: LocationManagerDelegate {
let locationManager: LocationManager
let geolocationDataProperty = MutableProperty<Geolocation?>(nil)
init() {
geolocationDataProperty.signal.observeValues { value in
//use the value for updating the UI
}
// Location Management
locationManager = LocationManager()
locationManager.delegate = self
locationManager.requestLocation()
}
// MARK: - LocationManagerDelegate
func didFindCurrentPosition(location: CLLocation) {
geolocationDataProperty.value = Geolocation(location: location)
}
}
然后我们可以尝试使用二元运算符来实现MVVM模式,因为直接引用模型视图中的UI元素绝对是一个坏主意: - )
看看这个article,这真的很有趣。
我不确定您的地图组件是否直接支持反应框架。
看它有“.reactive”扩展名,如果它可用于更新当前位置属性
如果它存在,那么&lt;〜运算符可以用来写类似于
的东西map.reactive.position <~ viewModel.geolocationDataProperty
如果它没有反应式扩展,那么您只需在viewcontroller中移动此代码
即可viewModel.geolocationDataProperty.signal.observeValues { value in
//use the value for updating the UI
}
答案 2 :(得分:0)
如果您的问题是在修改后有旧值。您可以尝试使用键值观察。添加您的属性以进行值观察,如
geolocationDataProperty.addObserver(self, forKeyPath: "value", options: [.new, .old], context: &observerContext)
每当修改geolocationDataProperty时,您将在委托方法
中收到该值 override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
let newValue = change?[.newKey] as? NSObject
let oldValue = change?[.oldKey] as? NSObject
//Add your code
}