Search code examples
swiftrx-swiftreactive-cocoareactive

Merge two streams with flatMapLatest


having a problem with combining to observables in flatMapLatest

Logic: on every activity next event, I want to combine it together with the next getCurrentLocation event, which happens after activityEvent was triggered, join them together in a tuple and then do something with it.

Currently, it is like this

ActivitiesController
    .start()
    .flatMapLatest { activity in 
        LocationController.shared.getCurrentLocation().map { ($0, activity) }
    }
    .subscribe(onNext: { (activity, currentLocation in
        print("")
    })
    .disposed(by: disposeBag)

Location code:

func getCurrentLocation() -> Observable<CLLocation> {
    self.requestLocationUseAuthorizationIfNotDetermined(for: .always)
    self.locationManager.requestLocation()
    return self.publishSubject.take(1) // take next object from the publish subject (only one)
}

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    guard let location = locations.last, location.horizontalAccuracy > 0 else {
        return
    }
    self.publishSubject.onNext(location)
}

Since we know that requestLocation() triggers didUpdateLocations, we were thinking the logic should work, but it doesn't

the result is locationManager not always updating and returning old values instead of new ones

Do you guys have any idea?


Solution

  • You need to use withLatestFrom instead of flatMapLatest.

    LocationController.shared.getCurrentLocation().withLatestFrom(activityEvent) {
        // in here $0 will refer to the current location that was just emitted and
        // $1 will refer to the last activityEvent that was emitted.
        return ($0, $1)
    }