Comments (7)
Hi @mcaylus The delegate is set
when you actually start subscribing to it and it is set
on the given CoreLocationManager
. This is how Rx
works in relation to all other delegates methods.
Now let me clarify the blurry path. The func requestLocation()
requires that you set
a Delegate
before you trigger it. Doing the same operation imperatively gives you that same error. According to the documentation " Only one location fix is reported to the delegate, after which location services are stopped" This in practice means it does require a delegate immediately to hand off the location information. So IMHO there is a pre-check within the CoreLocationManager
that throws the error *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Delegate must respond to locationManager:didUpdateLocations:
However you can still obtain the same result by using startUpdatingLocation()
and stopUpdatingLocation()
from rxcorelocation.
Hi @mcaylus I just tried your code you should change it a little bit take a look at this example it should work for your needs:
class ViewController: UIViewController {
let bag = DisposeBag()
let manager = CLLocationManager()
private var _service: CoreLocationService {
self.manager.requestWhenInUseAuthorization()
self.manager.startUpdatingLocation()
return CoreLocationService(locationManager: self.manager)
}
override func viewDidLoad() {
super.viewDidLoad()
_service.requestLocation().subscribe(onSuccess: {_coordinate in
print(_coordinate.latitude)
}, onError: {_error in
print(_error.localizedDescription)
}).disposed(by: bag)
}
}
protocol LocationService { }
class CoreLocationService: LocationService {
private let locationManager: CLLocationManager
private let disposeBag = DisposeBag()
init(locationManager: CLLocationManager) {
self.locationManager = locationManager
}
public func requestLocation() -> Single<CLLocationCoordinate2D> {
return Single.deferred {
return Observable.create { [unowned self] (observer) in
let locationError = self.locationManager
.rx
.didError
.subscribe( onNext: { (_, error) in
observer.onError(error)
})
let location = self.locationManager
.rx
.didUpdateLocations
.filter { $1.count > 0 }
.map { $1.last!.coordinate }
.subscribe(observer)
//self.locationManager.requestLocation()
let cancel = Disposables.create(with: {
self.locationManager.stopUpdatingLocation()
})
return CompositeDisposable(cancel, locationError, location)
}.take(1).asSingle()
}
}
}
from rxcorelocation.
Hi @bobgodwinx thanks for taking time to get back to me. It look like from your implementation that the .deferred is not needed anymore but the issue relate to usage of requestLocation
. Can you explain me why this method can't be used in this context? I wanted to use it as it requests a one-time delivery of the userβs current location which is what I need.
I have simplify my code by merging two stream:
func requestLocation() -> Single<CLLocationCoordinate2D> {
let locationStream: Observable<CLLocationCoordinate2D> = self.locationManager
.rx
.didUpdateLocations
.filter { $1.count > 0 }
.map { $1.last!.coordinate }
let errorStream: Observable<CLLocationCoordinate2D> = self.locationManager
.rx
.didError
.flatMap { return Observable.error($0.error) }
return Observable.merge(locationStream, errorStream)
.take(1).asSingle()
.do(onSubscribe: { [unowned self] in self.locationManager.startUpdatingLocation() },
onDispose: { [unowned self] in self.locationManager.stopUpdatingLocation() })
}
I still have some blurry parts:
- Can you provide me more insight on when the
CoreLocationManager
delegate methods are set (this relates to the error I got in my log)? - Does this implementation differ from extensions provided on the
RxSwift
official repository?
from rxcorelocation.
Hi @bobgodwinx thanks for the hint. From what you are saying I should be able to call requestLocation
on onSubscribed:
instead of onSubscribe:
then but this will crash as well. Do you see a potential bug here? Is implementation of RxCoreLocation
in sync with the extensions in RxSwift repo?
from rxcorelocation.
@mcaylus I can't really follow your last comment here is the link to the implementation and I can't find any bug within. Please kindly review it and if you find anything wrong that we can change please feel free to send in a PR and I will review it asap. Thanks
from rxcorelocation.
Let me compare the behavior on the RxSwift
repo for extensions on CoreLocation
with the extensions provided here on this repo and I will get back to you.
from rxcorelocation.
Hey @mcaylus I was running into a similar crash and log message going through a modified version of Ray Wenderlich's RxSwift's Chapter 13. I was using the implementation @bobgodwinx linked to above, but still getting a crash when I called locationManager.requestLocation
. His answer:
Now let me clarify the blurry path. The func requestLocation() requires that you set a Delegate before you trigger it. Doing the same operation imperatively gives you that same error. According to the documentation " Only one location fix is reported to the delegate, after which location services are stopped" This in practice means it does require a delegate immediately to hand off the location information
cleared it up for me. Additionally, if the locationManager.rx.didUpdateLocations
is subscribed to, then that subscription is disposed, it looks like the delegate proxy is torn down enough to also throw that NSException
. In my case, I needed something that would keep the subscription alive, even when there were no subscribers. As usual RxSwift has the thing: ConnectableObservable.publish()
let currentLocation = locationManager.rx.didUpdateLocations.map { locations in
return locations.first!
}
.filter { location in
return location.horizontalAccuracy < kCLLocationAccuracyHundredMeters
}.publish()
// Set the delegate by subscribing before `requestLocation` can be called.
// This subscription is disposed of immediately and doesn't consume the CLLocation
// requested becuase the observable is shared and the coordination is set up so that
// location isn't requested until the observable that is bound to the UI is subscribed as well.
currentLocation.take(1).debug("Ensure Delegate is Set").subscribe(onNext: { location in
print("debugged location")
}).disposed(by: bag)
currentLocation.connect().disposed(by: bag)
let geoInput = geolocationButton.rx.tap.asObservable()
.do(onNext: {
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.requestLocation()
}).share()
from rxcorelocation.
Related Issues (20)
- Why RxSwift Repo Example implement different? HOT 1
- Testing rx.placemark HOT 2
- Add support to RxSwift 4.4.0 HOT 6
- Same observer for UNUserNotificationCenter
- please update dependency 'RxCocoa' and dependency 'RxSwift' version to 4.4.0 HOT 1
- Observables does not send updated value when app enters foreground HOT 6
- Unable to resolve dependency HOT 3
- Circle CI HOT 1
- didReceiveRegion available for iOS 9.3 in RxCoreLocation 1.3.2 HOT 2
- Retrieve wrapper around CLGeocoder? HOT 2
- Carthage build failing on v1.5.1 HOT 4
- Build Failed: 'showsBackgroundLocationIndicator' is only available in iOS 11.0 or newer HOT 7
- Failure converting from Optional(<...>) to CLLocationManagerDelegate HOT 11
- Possible "memory effect" on .rx.location
- 'showsBackgroundLocationIndicator' is only available in iOS 11.0 HOT 19
- 'rangedRegions' is only available in Mac Catalyst 14.0 or newer
- Carthage failed
- When I want to get the placemark once, the console prints the warning.
- How to use with RxSwift 3.6.1? HOT 8
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rxcorelocation.