RxSwift Driver 第一次调用两次
RxSwift Driver calling twice on first time
我有一个 CoreLocation
管理器,它应该通过 RxSwift(及其扩展和 DelegateProxies)提供可观察的属性来处理所有 CLLocationManager
。 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 [=10=] {
case .authorizedAlways:
return true
default:
return false
}
}
location = locationManager.rx.didUpdateLocations.asDriver(onErrorJustReturn: []).flatMap {
return [=10=].last.map(Driver.just) ?? Driver.empty()
}
.map { [=10=].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
调用两次,因此访问请求视图显示了两次。我在这里错过了什么?
此致!
来自 startWith
文档:
StartWith
emit a specified sequence of items before beginning to emit the items from the source Observable
我没有尝试过,但如果您删除 startWith(status)
,您可能不会收到两次状态。
您似乎正在接收来自 observable 的下一个序列:
--------------------------------未授权----已授权------>
所以这行:
startWith(status) // status is unauthorized
你终于得到了这个:
--------未授权--------未授权----已授权----->
我有一个 CoreLocation
管理器,它应该通过 RxSwift(及其扩展和 DelegateProxies)提供可观察的属性来处理所有 CLLocationManager
。 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 [=10=] {
case .authorizedAlways:
return true
default:
return false
}
}
location = locationManager.rx.didUpdateLocations.asDriver(onErrorJustReturn: []).flatMap {
return [=10=].last.map(Driver.just) ?? Driver.empty()
}
.map { [=10=].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
调用两次,因此访问请求视图显示了两次。我在这里错过了什么?
此致!
来自 startWith
文档:
StartWith emit a specified sequence of items before beginning to emit the items from the source Observable
我没有尝试过,但如果您删除 startWith(status)
,您可能不会收到两次状态。
您似乎正在接收来自 observable 的下一个序列:
--------------------------------未授权----已授权------>
所以这行:
startWith(status) // status is unauthorized
你终于得到了这个:
--------未授权--------未授权----已授权----->