簡體   English   中英

RxSwift和CLLocation:嘗試獲取用戶位置時崩潰

[英]RxSwift and CLLocation : crash when trying to get user location

我在我的應用程序中使用RSwift庫。 我試圖獲取用戶位置,以便在網絡請求中發送它。 要獲取此位置,我需要使用Observables,因為該函數必須在用戶未授權位置時拋出錯誤。

此算法是在主線程之外的另一個線程中運行的許多Observable的連接數組的一部分(為了不凍結UI)。 我需要在主線程中執行“獲取用戶位置”功能,因為如果沒有在主線程中執行它崩潰,崩潰日志是:

fatal error: Executing on backgound thread. Please use `MainScheduler.instance.schedule` to schedule work on main thread

在上面的代碼中,有一個geolocation helper init(這是一個單例),並執行該方法來獲取用戶位置(或錯誤)。

private var authorized: Observable<Bool?>
private var location: Observable<CLLocationCoordinate2D>
private let locationManager = CLLocationManager()

private init() {
    locationManager.desiredAccuracy = LocationOptions.desiredAccuracy

    authorized = Observable.just(false)
        .map({ _ in CLLocationManager.authorizationStatus() })
        .concat(locationManager.rx_didChangeAuthorizationStatus)
        .distinctUntilChanged()
        .map({ authorizedStatus in
            switch authorizedStatus {
            case .AuthorizedAlways, .AuthorizedWhenInUse:
                return true
            case .NotDetermined:
                return nil
            case .Restricted, .Denied:
                return false
            }
        })
        .catchErrorJustReturn(false)

    location = locationManager.rx_didUpdateLocations
        .filter { $0.count > 0 }
        .map({ return $0.last!.coordinate })
}


func getLocation() -> Observable<Location> {
    return authorized
        .flatMap({ authorized -> Observable<CLLocationCoordinate2D> in
            guard let authorized = authorized else {
                self.locationManager.requestAlwaysAuthorization()
                return Observable.empty()
            }

            if authorized {
                self.startUpdating()
                return self.location
            } else {
                return Observable.error(
                    NSError(
                        domain:"",
                        code: 0,
                        userInfo:nil )
                )
            }
        })
        // We just need one position updated
        .take(1)
        .map({ coordinate in
            self.stopUpdating()

            let location = Location(longitude: coordinate.longitude, latitude: coordinate.latitude, latestUpdatedDate: NSDate())
            if location.isValid() {
                saveLocation(location)
            }
            return location
        })
        .doOnError({ error in self.stopUpdating() })
}

我在RXSwift地理位置示例( https://github.com/ReactiveX/RxSwift/pull/429 )中看到了一個可以使用Drivers處理它的類但我確實需要出錯並且驅動程序無法返回錯誤。

如果有人能幫我解決這個問題,我將不勝感激。

我已經嘗試將“.observeOn(MainScheduler.instance)”添加到2個observable中,但它凍結了UI ..也許有更好的方法來做到這一點而不凍結UI。

謝謝

@romroll, DelegateProxy現在只適用於RxCocoa中的主線程。 嘗試做這樣的事情

.map({ _ in CLLocationManager.authorizationStatus() })
        .observeOn(MainScheduler.instance)
        .concat(locationManager.rx_didChangeAuthorizationStatus)
        .observeOn(someOtherScheduler)
        .distinctUntilChanged()

希望這可以幫助。 如果沒有,你可以隨時通過提及@sergdort或其他人在RxSwiftSlack中與我聯系:)

您必須將擴展CLLocationManager + Rx.swift和RxCLLocationManagerDelegateProxy.swift復制到您的項目,因為它不再是RxCocoa的一部分

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM