[英]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.