1

アプリで RSwift ライブラリを使用しています。ネットワーク要求で送信するために、ユーザーの場所を取得しようとしています。この場所を取得するには、Observables を使用する必要があります。これは、ユーザーが場所を承認しなかった場合に関数がエラーをスローする必要があるためです。

このアルゴリズムは、(UI をフリーズさせないために) メイン スレッドとは別のスレッドで実行される多数の Observable の連結配列の一部です。メインスレッドで実行しないとクラッシュし、クラッシュログが次のようになるため、メインスレッドで「ユーザーの場所を取得」機能を実行する必要があります。

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

上記のコードには、地理位置情報ヘルパー 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 ) に、ドライバーで処理できるクラスが表示されますが、実際にはエラーが必要であり、ドライバーはエラーを返すことができません。

これを達成する方法について誰かが私を助けてくれれば幸いです。

私はすでに " .observeOn(MainScheduler.instance) " を 2 つのオブザーバブルに追加しようとしましたが、UI がフリーズします。UI をフリーズせずにこれを行うより良い方法があるかもしれません。

ありがとう

4

2 に答える 2