rxswiftcommunity / rxcorelocation Goto Github PK
View Code? Open in Web Editor NEWRxCoreLocation is a reactive abstraction to manage Core Location.
Home Page: https://github.com/RxSwiftCommunity/RxCoreLocation
License: MIT License
RxCoreLocation is a reactive abstraction to manage Core Location.
Home Page: https://github.com/RxSwiftCommunity/RxCoreLocation
License: MIT License
Hi @here I am trying to make a CoreLocation
service around this library. I have added a method that return a Single
of user position. Here is my current implementation:
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()
}
}
}
How can I ensure in this implementation that the subscription on the .didError stream is done before invocation self.locationManager.requestLocation()
. This is currently not happening in this implementation and I keep getting this error message on run time as a result: *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Delegate must respond to locationManager:didUpdateLocations:
RxCoreLocation/Sources/RxKeyPaths.swift
Line 25 in 9a50b4c
rangedRegions Deprecated
Use rangedBeaconConstraints instead.
import CoreLocation
import RxSwift
import RxCocoa
extension CLLocationManager: HasDelegate {
public typealias Delegate = CLLocationManagerDelegate
}
public class RxCLLocationManagerDelegateProxy
: DelegateProxy<CLLocationManager, CLLocationManagerDelegate>
, DelegateProxyType
, CLLocationManagerDelegate {
public init(locationManager: CLLocationManager) {
super.init(parentObject: locationManager, delegateProxy: RxCLLocationManagerDelegateProxy.self)
}
public static func registerKnownImplementations() {
self.register { RxCLLocationManagerDelegateProxy(locationManager: $0) }
}
internal lazy var didUpdateLocationsSubject = PublishSubject<[CLLocation]>()
internal lazy var didFailWithErrorSubject = PublishSubject<Error>()
public func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
_forwardToDelegate?.locationManager?(manager, didUpdateLocations: locations)
didUpdateLocationsSubject.onNext(locations)
}
public func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
_forwardToDelegate?.locationManager?(manager, didFailWithError: error)
didFailWithErrorSubject.onNext(error)
}
deinit {
self.didUpdateLocationsSubject.on(.completed)
self.didFailWithErrorSubject.on(.completed)
}
}
I noticed, with the current implementation, all the placemark
methods internally create an instance of CLGeocoder
.
I would like to ask, what is your opinion on exposing them publicly, and putting a Reactive
extension on CLGeocoder
?
I don't mind doing it myself, so long as the idea gets approved.
Benefits would be that you can do reverse geocoding on any CLLocation, not just the user's current location.
Our app requires the user to allow access to the devices location.
To handle this we first check if the location service is enabled, if it's not enabled we present a view controller letting the user know that he / she needs to enable the location service to continue.
The user would then most likely put the app in the background, enable the location service, open the app again.
In the view we present to the user when location service is disabled, we would like to automatically detect if the location service has been enabled, the code below is our attempt to react to the isEnabled
event.
viewDidLoad() {
super.viewDidLoad()
manager.rx
.isEnabled
.debug("isEnabled")
.subscribe(onNext: { isEnabled in
if isEnabled {
DispatchQueue.main.async {
self.dismiss(animated: true, completion: nil)
}
}
})
.disposed(by: bag)
}
When we test this by putting the app in the background then to foreground, no event is triggered.
Is this something the library is designed to handle?
If not, how would one go about creating this functionality in an app?
Configure repo to use Circle CI
verify and make sure it builds on every PR
I have this GeolocationService:
import CoreLocation
import RxSwift
import RxCoreLocation
class GeolocationService: NSObject {
var locationManager: CLLocationManager!
var currentPlacemark: CLPlacemark?
var currentLocation: CLLocation? {
return currentPlacemark?.location
}
var disposeBag = DisposeBag()
convenience init(withLocationManager loc: CLLocationManager) {
self.init()
locationManager = loc
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
locationManager.rx.placemark.subscribe(onNext: { [unowned self] placemark in
self.currentPlacemark = placemark
}).disposed(by: disposeBag)
}
deinit {
locationManager.stopUpdatingLocation()
}
func getCurrentLocation() -> (latitude: Double, longitude: Double)? {
guard let lat = currentLocation?.coordinate.latitude,
let lon = currentLocation?.coordinate.longitude else { return nil }
return (latitude: lat, longitude: lon)
}
func getCurrentAddress() -> Address? {
guard let cPlacemark = currentPlacemark else { return nil}
let address = Address(street: cPlacemark.name, zipCode: cPlacemark.postalCode, city: cPlacemark.locality, country: cPlacemark.country)
return address
}
}
Despite any design flaw it's working properly.
My question is, how can I unit test the placemark subscription?
Due to this dependency any other method's test would be trivial if I could just be able to test the subscription.
Looking forward for any thoughts, thanks in advance!
please update dependency 'RxCocoa' and dependency 'RxSwift' version to 4.4.0
When running the carthage command to update RxCoreLocation v1.5.1 it fails with:
framework not found Nimble
It is a great library thank you.
I'm trying to observe UNUserNotificationCenter authorization status but I could not find a similar thing like this.
If you consider building such a thing, that'd be awesome.
Hi,
I am using several instances of CLLocationManager
(configured slightly differently) potentially at the same time and scoped to dedicated Rx streams (for each, I initiate a new CLLocationManager()
that I specifically configure, then I call startUpdatingLocation()
at stream's subscription, and I call stopUpdatingLocation()
at the disposal) returning what the RxCoreLocation extension .rx.location
provides me in the meantime.
In this context, I have, among other things, one method that returns to me an Observable<CLLocation>
every second (distanceFilter == kCLDistanceFilterNone) and another every 30m traveled (distanceFilter == 30).
In a very specific case, I noticed a kind of "memory effect" (without fully understanding it yet) when I subscribed to a new 30m stream it returned to me all the data of the last 1Hz stream that I disposed, a few seconds before. It's very strange.
Is this strange behaviour possible there?
public var location: Observable<CLLocation?>
let updatedLocation = self.didUpdateLocations.map { $1.last } // <--- possible memory effect here?
let location = self.observe(CLLocation.self, .location)
return Observable.of(location, updatedLocation).merge()
}
Thanks
Is it possible to use with RxSwift 3?
i found error 'showsBackgroundLocationIndicator' is only available in iOS 11.0 inside RxKeyPaths.swift, how to solve this problem
The package dependency graph can not be resolved; unable find any available tag for the following requirements:
https://github.com/RxSwiftCommunity/RxCoreLocation.git โ 1.4.0..<2.0.0
A human readable documentation explaining how CLLocationManager
works and how to use the RxCoreLocation
in solving specific need where applicable.
When I build my project at Xcode 12.5 beta, I got result that build failed
xcode showed error message
'showsBackgroundLocationIndicator' is only available in iOS 11.0 or newer
in RxCoreLocation 1.5.0
Hi,
first of all thank you for maintaining this library ๐
We have been using RxCoreLocation for some time now and every then and now we see this crash:
Fatal error: Failure converting from Optional(<GjlTsjYFHdNgFERt: 0x282062300>) to CLLocationManagerDelegate: file RxCocoa/RxCocoa.swift, line 153
At first we saw that users that crashed had jailbroken devices so immediate though was that they are just messing with location manger. However, more recently we received few crashes that happened on devices that were not jailbroken i.e.:
Fatal error: Failure converting from Optional(<GjlTsjYFHdNgFERt: 0x280045400>) to CLLocationManagerDelegate: file RxCocoa/RxCocoa.swift, line 153
.
We are not doing anything magical apart from subscribing to didChangeAuthorization
, didUpdateLocations
.
This is affecting only super small fraction of our users, but nevertheless it is interesting why this could happen. Perhaps you have any insights?
In implementation to return the user's current or location Placemark
automatically when location is updated.
The ideal type here will be CLPacemark
property which also contains the address of the updated CLLocation
Tested on "master" and 1.5.1
carthage update --use-xcframeworks --platform iOS
This usually indicates that project itself failed to compile.
./Carthage/Checkouts/RxCoreLocation/Sources/Helpers.swift:10:12: error: no such module 'RxSwift'
import RxSwift
^
/var/folders/jk/yh46dz450lg28bywvt4jyslm0000gn/T/carthage-xcframework-SxNw/RxCocoa.framework/Modules/RxCocoa.swiftmodule/arm64-apple-ios.swiftinterface:7:8: error: no such module 'RxCocoaRuntime'
import RxCocoaRuntime
^
/var/folders/jk/yh46dz450lg28bywvt4jyslm0000gn/T/carthage-xcframework-SxNw/RxCocoa.framework/Modules/RxCocoa.swiftmodule/arm64-apple-ios.swiftinterface:7:8: error: no such module 'RxCocoaRuntime'
import RxCocoaRuntime
^
/var/folders/jk/yh46dz450lg28bywvt4jyslm0000gn/T/carthage-xcframework-SxNw/RxCocoa.framework/Modules/RxCocoa.swiftmodule/arm64-apple-ios.swiftinterface:7:8: error: no such module 'RxCocoaRuntime'
import RxCocoaRuntime
^
/var/folders/jk/yh46dz450lg28bywvt4jyslm0000gn/T/carthage-xcframework-SxNw/RxCocoa.framework/Modules/RxCocoa.swiftmodule/arm64-apple-ios.swiftinterface:7:8: error: no such module 'RxCocoaRuntime'
import RxCocoaRuntime
when i execute the code:
manager.rx.placemark.take(1).subscribe()
the console prints the warning:
โ ๏ธ Reentrancy anomaly was detected.
> Debugging: To debug this issue you can set a breakpoint in /Users/huangqc/Library/Developer/Xcode/DerivedData/HiNen-cpfnagrkwcupnlcdabhuytikjqaf/SourcePackages/checkouts/RxSwift/Sources/RxSwift/Rx.swift:96 and observe the call stack.
> Problem: This behavior is breaking the observable sequence grammar. `next (error | completed)?`
This behavior breaks the grammar because there is overlapping between sequence events.
Observable sequence is trying to send an event before sending of previous event has finished.
> Interpretation: This could mean that there is some kind of unexpected cyclic dependency in your code,
or that the system is not behaving in the expected way.
> Remedy: If this is the expected behavior this message can be suppressed by adding `.observe(on:MainScheduler.asyncInstance)`
or by enqueuing sequence events in some other way.
โ ๏ธ Reentrancy anomaly was detected.
> Debugging: To debug this issue you can set a breakpoint in /Users/huangqc/Library/Developer/Xcode/DerivedData/HiNen-cpfnagrkwcupnlcdabhuytikjqaf/SourcePackages/checkouts/RxSwift/Sources/RxSwift/Rx.swift:96 and observe the call stack.
> Problem: This behavior is breaking the observable sequence grammar. `next (error | completed)?`
This behavior breaks the grammar because there is overlapping between sequence events.
Observable sequence is trying to send an event before sending of previous event has finished.
> Interpretation: This could mean that there is some kind of unexpected cyclic dependency in your code,
or that the system is not behaving in the expected way.
> Remedy: If this is the expected behavior this message can be suppressed by adding `.observe(on:MainScheduler.asyncInstance)`
or by enqueuing sequence events in some other way.
Hi,
I was working with a native CoreLocation implementation for a geofencing feature and now I'm moving everything to RxSwift.
It was working just fine before, my project's deployment target is iOS 9.0, but I don't understand why the API below is marked for iOS 9.3 or above if the three CoreLocation methods that is using are available from iOS 4.0/5.0.
@available(iOS 9.3, OSX 10.11, *)
public var didReceiveRegion: RxCocoa.ControlEvent<CLRegionEvent> { get }
Could this be an issue?
Thank you!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.