I'm starting using ReactiveCocoa and I'm still struggling with some basic concepts:
init
in my view model)didFindCurrentPosition
is called)viewDidLoad
in my view controller)viewDidLoad
)My problem is: after step 2 is achieved, if no other event is sent on the signal, my view controller doesn't get notified.
How can my view controller get access to the last value from the signal? (ie how to get access at step 3 to a value emitted at step 2?)
Thanks for your help.
PS: ReactiveCocoa looks like a great library but I'm puzzled by the state of the documentation. IMHO, it is not very clear and lacks some clear guides on how to use it.
The view model:
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)
}
}
The view controller:
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")
}
}
}
You already have a Property
that holds the latest value emitted. Instead of using the property's signal
use the producer
. That way when you start the producer
you will get the current value first (in none was sent you will get nil).
Cf. the documentation:
The current value of a property can be obtained from the value getter. The producer getter returns a signal producer that will send the property’s current value, followed by all changes over time. The signal getter returns a signal that will send all changes over time, but not the initial value.
So, regarding the code in the question, the viewDidLoad
method should do something like the following:
viewModel.geolocationDataProperty
.producer
.start(on: UIScheduler())
.startWithValues { geolocation in
debugPrint("GOT GEOLOCATION")
}