2017-01-24 1 views
0

J'ai un gestionnaire CoreLocation qui devrait gérer tous les CLLocationManager en offrant des propriétés observables via RxSwift (et ses extensions et DelegateProxies). LocationRepository ressemble à ceci:RxSwift Pilote appelant deux fois la première fois

class LocationRepository { 
    static let sharedInstance = LocationRepository() 
    var locationManager: CLLocationManager = CLLocationManager() 
    private (set) var supportsRequiredLocationServices: Driver<Bool> 
    private (set) var location: Driver<CLLocationCoordinate2D> 
    private (set) var authorized: Driver<Bool> 

    private init() { 
     locationManager.distanceFilter = kCLDistanceFilterNone 
     locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation 

     supportsRequiredLocationServices = Observable.deferred { 
      let support = CLLocationManager.locationServicesEnabled() && CLLocationManager.significantLocationChangeMonitoringAvailable() && CLLocationManager.isMonitoringAvailable(for:CLCircularRegion.self) 
      return Observable.just(support) 
     } 
     .asDriver(onErrorJustReturn: false) 

     authorized = Observable.deferred { [weak locationManager] in 
      let status = CLLocationManager.authorizationStatus() 
      guard let locationManager = locationManager else { 
       return Observable.just(status) 
      } 
      return locationManager.rx.didChangeAuthorizationStatus.startWith(status) 
     } 
     .asDriver(onErrorJustReturn: CLAuthorizationStatus.notDetermined) 
     .map { 
      switch $0 { 
      case .authorizedAlways: 
       return true 
      default: 
       return false 
      } 
     } 

     location = locationManager.rx.didUpdateLocations.asDriver(onErrorJustReturn: []).flatMap { 
      return $0.last.map(Driver.just) ?? Driver.empty() 
     } 
     .map { $0.coordinate } 
    } 

    func requestLocationPermission() { 
     locationManager.requestAlwaysAuthorization() 
    } 
} 

Mon présentateur écoute alors des changements sur les propriétés du référentiel. LocatorPresenter ressemble à ceci:

class LocatorPresenter: LocatorPresenterProtocol { 
    weak var view: LocatorViewProtocol? 
    var repository: LocationRepository? 
    let disposeBag = DisposeBag() 

    func handleLocationAccessPermission() { 
     guard repository != nil, view != nil else { 
      return 
     } 

     repository?.authorized.drive(onNext: {[weak self] (authorized) in 
      if !authorized { 
       print("not authorized") 
       if let sourceView = self?.view! as? UIViewController, let authorizationView = R.storyboard.locator.locationAccessRequestView() { 
        sourceView.navigationController?.present(authorizationView, animated: true) 
       } 
      } else { 
       print("authorized") 
      } 
     }).addDisposableTo(disposeBag) 
    } 
} 

Il fonctionne, mais je reçois le Driver deux fois pour appeler la première fois que j'essaie d'obtenir le statut d'autorisation, de sorte que la vue sur la demande d'accès obtient présenté deux fois. Qu'est-ce que j'oublie ici?

Cordialement!

Répondre

1

De startWith documentation:

startwith émettent une séquence spécifiée d'éléments avant de commencer à émettre les éléments de la source Observable

Je ne l'ai pas essayé, mais probablement si vous retirez startWith(status) vous ne recevrez pas le statut deux fois.

Il semble que vous recevez la séquence suivante de l'observable:

------------------------------ --- ---- autorisée non autorisée ----->

donc avec la ligne:

startWith(status) // status is unauthorized 

vous obtenez finalement celui-ci:

------- unauthorized- -------- non autorisé ---- autorisé ----->

+0

Merci, c'était ça. Il me donnait deux fois le statut actuel chaque fois que je m'abonnais à l'Observable pour la première fois. enlever startWith travaillé. – edulpn

+0

Cela fonctionnera, mais vous pouvez utiliser '.distinctUntilChanged()' ater map to boolean, qui se déclenchera à nouveau si le statut est différent, et non pas en double. –