How to check Location Manager is running or not in iOS? - 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.

Related

Working with location updates when app is terminated

I am working on a project in which i am trying to get location updates in all states, even when app is terminated. I have used all possible solutions but still it's not working in case of termination.For now I want to clear a doubt - I am using startUpdatingLocation() for foreground and background. As we know that startMonitoringSignificantLocationChanges() is the only method that relaunch app in case of any location update. Can we call "startMonitoringSignificantLocationChanges()" in applicationWillTerminate() method? and Will that work and relaunch app when there is any significant location update? Please tell me.
Thank!!
You cannot do that in applicationWillTerminate(),because closure won't return a value right now.If you want to get user location all the time,try Background Mode.
This is the description in Apple Document:
In such a case, the options dictionary passed to the application:willFinishLaunchingWithOptions: and application:didFinishLaunchingWithOptions: methods of your app delegate contains the key UIApplicationLaunchOptionsLocationKey to indicate that your app was launched because of a location event. Upon relaunch, you must still configure a location manager object and call this method to continue receiving location events. When you restart location services, the current event is delivered to your delegate immediately. In addition, the location property of your location manager object is populated with the most recent location object even before you start location services.
It clearly tells you how to get the location.

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:

NSUserDefaultsDidChangeNotification Doesn't Fire After Sending stopUpdatingLocation to CLLocationManager

Currently in this iOS application I have added some controller I've written as an observer to the [NSNotificationCenter defaultCenter] to observe NSUserDefaultsDidChangeNotification.
- (void)startObservingDefaults
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(userDefaultsDidChange)
name:NSUserDefaultsDidChangeNotification
object:nil];
}
The user default that I am watching should enable or disable a CLLocationManager using a PSToggleSwitchSpecifier from the settings menu. After starting the application and sending startUpdatingLocation to a CLLocationManager ivar I can go to the settings menu and disable the location manager. My selector userDefaultsDidChange will then check if that default is enabled or disabled. If it is enabled, I send startUpdatingLocation to the location manager instance, if it is disabled I send stopUpdatingLocation to it. Each path logs its action like so
- (void)userDefaultsDidChange
{
if ([self duringOperationHours] && [self isEnabled]) {
NSLog(#"\n\n\nWithin Operating Hours.\n\n\n");
[_locationManager startUpdatingLocation];
NSLog(#"Enabled Location Manager.");
} else {
NSLog(#"\n\n\nDisabled or Outside of Operating Hours.\n\n\n");
[_locationManager stopUpdatingLocation];
NSLog(#"Disabled Location Manager.");
}
}
I have other settings that control time of day (start time and end time ex. 6AM to 6PM). If I change one of those settings and the current time is still within that time range the log will show that it is still "Within Operating Hours." and that the location manager is enabled.
If I change it so that the location manager gets disabled, it does log both NSLog statements in my method above and it DOES shut down the location manager.
The problem comes when I try to start it back up. So say I am in the settings and it is enabled. I disable it, the log shows it is disabled and the little icon for GPS disappears, if I then re-enable it the notification doesn't fire at all. In fact, no other settings even in other child panes don't fire until I go back to the application. (I've tried a dispatch_async inside the userDefaultsDidChange method to both main_queue and global_queue and saw no change).
MY QUESTION IS am I doing something wrong that might cause this to lock up with the location manager? Or is this some internal queue issue to CLLocationManager? Or something else? Perhaps CLLocationManager will only start if the application is in the foreground? Even if that were the case I should still be seeing the log statements that it at least attempted to start the location manager right?
Nevermind I figured it out.
The observation of the NSNotificationCenter on the NSUserDefaultsDidChangeNotification DOES NOT wake up the application. What was happening was the CLLocationManagerDelegate protocol applied to my controller would "wake up" the application to do what it needed to the with CLLocations that were received. Upon this waking up, the observation of change to some user defaults in the NSNotificationCenter would fire off my selector userDefaultsDidChange.
As long as the CLLocationManager was updating and there to alert the application it would allow the controller to call the designated selector. When the CLLocationManager was no longer updating the location the application would not be woken up and therefore not know any user defaults had changed until the app returned to the foreground.
I will update this answer if I come up with a better solution for this odd observation scenario.

How does iOS knows which location manager delegate to call on region monitoring while the app is not running?

I might be confusing how region monitoring works, but this is what i have so far:
I am registering a region to monitor through my location manager, which is implemented on a singleton class, this singleton is also set as the delegate of the location manager so the implemented method is being called.
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
This works totally as expected, if the app is active or suspended the method is being called. It also makes total sense because the class has been already loaded and when the region enter event occurs iOS sends this even to my app which calls the location manager who registered (probably has a reference to it) and in turn it calls whatever delegate was also registered along it (since the class is there ready and loaded).
The issue is, what happens when the app has been killed? Is it first launched into the background? How does iOS know what delegate method to call, and if it has already been loaded?
When your app has been killed and gets started for a location update there can't be a location manager delegate yet and as such there are no notifications delivered to that delegate. The system can't know which of your classes should be used as a location manager delegate or how to instantiate it.
Instead your application:didFinishLaunchingWithOptions: gets called as usual, but the UIApplicationLaunchOptionsLocationKey is set in the options dictionary. That tells your app that you need to instantiate a location manager and set it's delegate. Only after you did this the delegate gets called with the region updates.

Continue process after user has allowed sharing and location found

I have something like this:
CLLocationManager *locManager = [[CLLocationManager alloc] init];
locManager.delegate = self;
locManager.desiredAccuracy = kCLLocationAccuracyBest;
[locManager startUpdatingLocation];
But I need to get below the latitude and longitude user. Obviously, trying to obtain locManager.coordinate just below the startUpdatingLocation my application crashes.
How can I make a condition to perform a process after the user allows sharing of location and it has been found?
Thanks in advance.
After calling startUpdatingLocation it can take some time until you get a location. The system first checks if location services are enabled for the app and asks the user to allow location services. The GPS hardware first needs to be turned on. It takes some time until it can fix the position.
So you should update the UI to show the user that there is something going on in the background. Consider using a UIActivityIndicatorView and maybe set userInteractionEnabled of the view to NO. Also it is a good practice to give the user the option to cancel the operation.
In your delegate you must implement these 2 methods:
– locationManager:didUpdateToLocation:fromLocation:
– locationManager:didFailWithError:
Here you can remove the UIActivityIndicatorView and reenable user interaction.
In case of success you can use the coordinate of the CLLocationManager to do whatever you want. In case of failure show an error alert.
Call stopUpdatingLocation when you don't need location services anymore to save battery.

Resources