iOS - How - startMonitoringSignificantLocationChanges works - ios

How the iOS system trigger the method -startMonitoringSignificantLocationChanges?
Will the system trigger this automatically?
What if I want every 500m trigger the -startMonitoringSignificantLocationChanges how can I set my locationManager?

call locationManager.startMonitoringSignificantLocationChanges() will update your didUpdateLocations method when iOS detect location update approximately 500 meters.
System will call this automatically until you explicitly call stopMonitoringSignificantLocationChanges()
iOS give his best to provide this you don't have to do anything
For more Apple Doc

Related

startMonitoringSignificantLocationChanges not starting instantly

I'm working on a navigation application, everything working in terminated, background and fore ground state.
But in one scenario of terminated state startMonitoringSignificantLocationChanges is not handling itself.
The issue is
when i start the startMonitoringSignificantLocationChanges and killed the app, then I'm getting location event like after 0.5-1km because of that it draws straight line from my initial position to the first location event I get.But when the location event starts coming then everything work smoothly
Same issue occur again when in the middle of travelling I open the application to check my route status and then kill the application, again location events start coming after 0.5-1km and a straight line was drawn.
The code is straight
significantLocationManager = CLLocationManager()
significantLocationManager?.allowsBackgroundLocationUpdates = true
significantLocationManager?.pausesLocationUpdatesAutomatically = false
significantLocationManager?.requestAlwaysAuthorization()
and call the tracking when user needs by
significantLocationManager?.startMonitoringSignificantLocationChanges()
Rest I have handled the incoming location event in the app delegate to save in db.
So question is how should I handle this scenario in which straight line is drawn ?
From Apple documentation:
Apps can expect a notification as soon as the device moves 500 meters or more from its previous notification. It should not expect notifications more frequently than once every five minutes. If the device is able to retrieve data from the network, the location manager is much more likely to deliver notifications in a timely manner.
If you need to receive location updates as soon as possible I'd recommend to use startUpdatingLocation() with desired distanceFilter of CLLocationManager.
You can use Location update in background mode. From Apple documentation:
When you start the significant-change location service, a recently
cached value may be reported to your delegate immediately. As new
location data is obtained, the location manager calls your delegate's
locationManager(_:didUpdateLocations:) method with the updated values.
The locations parameter always contains at least one location and may
contain more than one. Locations are always reported in the order in
which they were determined, so the most recent location is always the
last item in the array, as shown in Listing 2.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let lastLocation = locations.last!
// Do something with the location.
}
Here you will get the last cached location in your device, and it should be very precise if you have location service turned on in your device of course.
Another thing to know is this. Note form Apple:
The significant-change location service requires authorization. For
more information Requesting Authorization for Location Services.

CLLocationManager.requestLocation() takes about 10 seconds

CLLocationManager.requestLocation() takes around 10 seconds to fire didUpdateLocations event.
Here are the attributes set for the CLLocationManager
let locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = 10
locationManager.requestWhenInUseAuthorization()
locationManager.requestLocation()
As per the documentation this can take several seconds.
This method returns immediately. Calling it causes the location manager to obtain a location fix (which may take several seconds) and call the delegate’s locationManager(_:didUpdateLocations:) method with the result.
But can this take 10 long seconds? Or am I missing something?
If you switch out the
locationManager.requestLocation()
for
locationManager.startUpdatingLocation()
then didUpdateLocations will start firing immediately. This should solve your problem.
TL;DR
requestLocation() is a convenient method provided by Apple which under the hood will run startUpdatingLocation() , retrieve multiple location data, and select the most accurate one to pass to delegate, and call stopUpdatingLocation()
This process can take up to 10 seconds (which is around the timeout limit) if it can't decide which location data is the best.
I think you have a false premise. That Google is always faster. I'm guessing that your building app from scratch and the app has no access to cache. Otherwise GoogleMaps can also sometimes take more than 3 seconds. Obviously I don't know the exact specifics but I just think when you're using GoogleMaps you're using it as a user and now when you're developing your own app you're thinking about it as a developer ie you're being more meticulous about it.
Also to have the best of comparisons make sure you set your desiredAccuracy to BestForNavigation, distanceFilter to 0 and activityType to .automotive. That's normally what navigation apps are doing.
Leo's comment is also important: Make sure you update the UI from the main queue
And as mentioned by both highly experienced in Core-Location users: programmer and Paulw11:
When you call startUpdatingLocation on the location manager you must give it time to get a position. You should not immediately call stopUpdatingLocation. We let it run for a maximum of 10 seconds or until we get a non-cached high accuracy location.
I changed .desiredAccuracy to kCLLocationAccuracyKilometer and my .requestLocation() now returns the position immediately
I found the following line in my Console logs:
Ignoring requestLocation due to ongoing location.
No idea what's going on. My app doesn't call startUpdatingLocation() at all. But when I keep the app running I can see that locationManager(_:didUpdateLocations:) is called periodically.
Once I put stopUpdatingLocation() in front of the requestLocation() it's as fast as expected:
locationManager.stopUpdatingLocation()
locationManager.requestLocation()

Beacon / IOS CLLocationManager get current region

I'm doing a program who is looking for beacon, I implemented CLLocationManager and my apps works except one point.
I'm calling startMonitoringForRegion() in order to get the didEnterRegion/didExitRegion callback. Inside these function I'm doing startRangingBeaconsInRegion()/stopRangingBeaconsInRegion() in order to get precise information when the user is in the beacon area.
My issue is quite simple, if the app is started when the user is already in the beacon range, didEnterRegion is not called.
I'm looking for a function like isInRegion() so that when my app start I could do startMonitoringForRegion() then isInRegion() and startRangingBeaconsInRegion() if the user is already in the region.
My current workaround is to call startRangingBeaconsInRegion() when the app start, then in the didRangeBeacons callback, I'm doing stopRangingBeaconsInRegion() if no beacon is found.
I don't think that it's a very clean way and would like to replace by something better if possible
Thanks,
You can use the locationManager:didDetermineState:forRegion: callback, which tells you if you are either Inside, Outside or Unknown.
You can force yourself to get a callback by calling
locationManager.requestStateForRegion(region)
when your app starts up.
See more here: https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocationManagerDelegate_Protocol/#//apple_ref/occ/intfm/CLLocationManagerDelegate/locationManager:didDetermineState:forRegion:

didEnterRegion fire when app is terminated?

I've implemented the use of GeoFences in my app. I've created a new CLLocationManager property and initialised it in my app's viewDidLoad method simply like so:
[[self.locationManager alloc] init];
I set the delegate to self, start monitoring for regions using startMonitoringForRegion:
Then, I emulate my location while running it using Xcode and the methods didEnterRegion and didExitRegion. The app works perfect while running, but I haven't got the chance to test it as I don't know how to emulate my location while the app is terminated, see my other question
Therefore, I was hoping to get some answers on these questions:
Can I manage background work just like normal with the didEnterRegion and didExitRegion methods? Like calculating, etc?
If my app is terminated, I enter a region, open my app - are my variables from didEnterRegion initialised and set up then?
Do I need to do anything else to set it up to work when my app is terminated, except for the normal CLLocationManager setup that I've done so far?
Thanks!

How to check Location Manager is running or not in iOS?

I am creating location based application, I am implementing Delegate method of CLLocationManager,
I know there are two methods to start and stop location methods are:
[locationManger startUpdatingLocation];
[locationManger stopUpdatingLocation];
but i want to check is location manager is already running? is there any method for that like,
isLocationManagerRunning
if locationmanager is not running i have to start it.
I don't want to put BOOL in delegate method for checking it.
You don't need to check if it is running or not, if you are not sure then just call startUpdatingLocation on your location manager.
If it is not running it will start, if it is running, it doesn't incur an overhead to start it again. As the documentation says:
Calling this method several times in succession does not automatically result in new events being generated. Calling stopUpdatingLocation in between, however, does cause a new initial event to be sent the next time you call this method.

Resources