Драйвер RxSwift вызывает дважды в первый раз

У меня есть менеджер CoreLocation, который должен обрабатывать все CLLocationManager, предлагая наблюдаемые свойства через RxSwift (и его расширения и DelegateProxies). LocationRepository выглядит так:

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()
    }
}

Затем мой докладчик слушает изменения в свойствах репозитория. LocatorPresenter выглядит так:

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)
    }
}

Это работает, но я дважды получаю вызов Driver в первый раз, когда пытаюсь получить статус авторизации, поэтому представление запроса на доступ представляется дважды. Что мне здесь не хватает?

С уважением!


person edulpn    schedule 24.01.2017    source источник


Ответы (1)


Из документации startWith:

StartWith выдает указанную последовательность элементов перед тем, как начать выдавать элементы из исходного Observable

Я не пробовал, но, вероятно, если вы удалите startWith(status), вы не получите статус дважды.

Кажется, вы получаете следующую последовательность от наблюдаемого:

-------------------неавторизованный----авторизованный----->

Итак, со строкой:

startWith(status) // status is unauthorized

вы, наконец, получите это:

-------неавторизованный---------неавторизованный----авторизованный----->

person xandrefreire    schedule 25.01.2017
comment
Спасибо, это было. Он давал мне текущий статус дважды каждый раз, когда я подписывался на Observable в первый раз. удаление startWith сработало. - person edulpn; 25.01.2017
comment
Это будет работать, но вы можете использовать .distinctUntilChanged() ater map для логического значения, которое будет срабатывать снова только в том случае, если статус отличается, а не дублирует вызовы. - person Ramon Vicente; 24.03.2017