私のアプリでRSwiftライブラリを使用しています。私はネットワーク要求でそれを送信するためにユーザーの場所を取得しようとしています。この場所を取得するには、Observablesを使用する必要があります。これは、ユーザーが場所を承認しなかった場合にエラーをスローする必要があるためです。RxSwiftとCLLocation:ユーザーの場所を取得しようとするとクラッシュします
このアルゴリズムは、(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)ドライバとそれを扱うことができるクラスで見たが、私は実際にエラーを返すことができないエラーとドライバを持っている必要があります。
これを達成する方法についてお手伝いいただければ幸いです。
私は既に2つの観測値に ".observeOn(MainScheduler.instance)"を追加しようとしましたが、UIがフリーズしています。UIをフリーズすることなくこれを行うより良い方法があります。
おかげで今のRxCocoaにメインスレッド上でのみ動作しますDelegateProxy
お返事ありがとうございました@sergdort。私はあなたの提案を試みたが、うまくいかなかった。私も '.observeOn(MainScheduler.instance)'だけを追加しようとしましたが、 "バックグラウンドスレッドで実行する"問題もあります。ジオロケーションコードの呼び出しをすべて削除すると動作し、 'rx_didChangeAuthorizationStatus'を呼び出すコードだけを追加するとクラッシュします。これは本当にこの方法に関連しているようです。 – romroll
同じ問題が見つかりました。 RxコードがlocationManager(_ manager:CLLocationManager、didUpdateLocations locations:[CLLocation])のコールバックにある場合、observeOnまたはsubscribeOnは期待通りに機能しません。すべてのコードはメインスレッドだけで実行されます。かなり奇妙 – User9527