IOS Swift User Location Authorization - ios

I have an app that is tracking a User's location. I have much experience with this and have requested when in use Authorization and have added the key to my P-List, however I still receive this error:
"Trying to start MapKit location updates without prompting for
location authorization. Must call -[CLLocationManager
requestWhenInUseAuthorization] or -[CLLocationManager
requestAlwaysAuthorization] first."
The location Manager that I am using is not in the ViewController but in another class.

It doesn't matter where those methods are called from, so you could call either of those methods either from your app delegate's applicationDidFinishLaunching method (these authorization methods run asynchronously) or in the viewDidAppear method of your very first view controller.

check the [CLLocationManager authorizationStatus] before setting mapView.showsUserLocation = YES or startUpdatingLocation
Make sure that your CLLocation variable is strong.
(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status == kCLAuthorizationStatusAuthorizedWhenInUse) //or kCLAuthorizationStatusAuthorizedAlways
{
self.mapView.showsUserLocation = YES;
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
You must use anyone of the authorization
self.locationManager.requestWhenInUseAuthorization(); or self.locationManager.requestAlwaysAuthorization();
Anyhow the warning will not come for the second time after the user accept the permission

Related

CLLocationManager permissions

I'm working on permissions for location, problem is next:
User turned off location services from privacy and installed the app. I have line of code that is asking to enable location services: if (![CLLocationManager locationServicesEnabled] || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied)... and this is working pretty fine. Problem is that app don't ask for allowing app to use location, then it asks the second time. Code for asking for permission:
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
NOTE: Everything works fine if locations services enabled, it asks for approval first time.
EDIT: Full code for permissions:
-(void)setupPermissions
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
if (![CLLocationManager locationServicesEnabled] || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
}
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
}
Your code makes no sense. You have this:
if (something) {
}
if (somethingelse) {
[self.locationManager requestWhenInUseAuthorization];
}
So you have one if that is empty, and another if that always runs regardless of what the first if does. Perhaps you meant to use else if for the second condition?
(And keep in mind that, as you've already been told, calling requestWhenInUseAuthorization is pointless unless the status is NotDetermined.)
The only time you can get iOS to request user permissions is when the authorization status is NotDetermined.
If a user has denied your app, the only way you can get them to be prompted again is to uninstall the app, or reset privacy on the device.
The easiest approach would be to provide an alert controller with a link to settings so that they can turn it on themselves.
Here is a link that shows the process for doing that.

iOS receive notification when user moving

Ive been struggling with a way to retrieve information periodically from a BT device. My bluetooth device is located in a vehicle typically, so my question is if its possible to use say... (if user traveling > 10km/h) to run a task. Or on major location change.
Is is possible to get a really course location that I would be able to use to get a general idea of wether the user is moving? I only need it to trigger once every couple days(while user is driving). The user never interacts with my app after initial setup.
Thanks.
Implementation of cmyr's suggestion:
CLLocationManager *locationManager;
int badge_count = 0;
- (void)startSignificantChangeUpdates
{
// Create the location manager if this object does not
// already have one.
if (nil == locationManager)
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.pausesLocationUpdatesAutomatically = YES;
locationManager.activityType = CLActivityTypeAutomotiveNavigation;
[locationManager requestAlwaysAuthorization];
locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
locationManager.distanceFilter = 500; // meters
[locationManager allowDeferredLocationUpdatesUntilTraveled:501 timeout:-1];
[locationManager startMonitoringSignificantLocationChanges];
[locationManager startUpdatingLocation];
}
// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
badge_count++;
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:badge_count];
NSLog(#"Location Event WOOT!");
}
Unfortunately I cannot get the event to trigger. I have added Location updated to the apps plist.
The above code is contained inside my app delegate.m file
Core Location has a set of APIs for specifically this use-case, which Apple refers to as Significant Location Change Monitoring.
From the documentation:
The significant-change location service delivers updates only when there has been a significant change in the device’s location, such as 500 meters or more.
This API only updates your location when and if you've traveled the specified distance. It does not provide constant updates. If you need constant updates, you will have to use the standard location service.

CLLocationManager delegate not called

I am using iBeacons, but am running into a small problem.
On first use the user needs to give permission, we then following is called:
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
[_locationManager requestAlwaysAuthorization];
However, I expected the following delegate method to be called:
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
NSLog(#"Auth status changed: %i", status);
if(status > 3){
// Check if we have to start monitoring beacons
NSLog(#"Do we need to initialise after auth given?");
//[self initialiseLocations];
}
}
I am running iOS 8.0.2, so not sure if this is a bug
This answer might help... it solved it for me at least. Also this website was a good walkthrough for this issue as well.
It looks like you are calling the requestAlwaysAuthorization correctly, but do you call startUpdatingLocation anywhere? Also, double check that in your Info.plist you have the appropriate key and string value added (NSLocationAlwaysUsageDescription since you're using requestAlwaysAuthorization).

Issue in getting current location

I want to get current location of device. Code works fine normally. It gives location if user has not changed app authorization status for location service. I am also able to check if user has denied permission for location service.
Issue is when user deauthorizes the app to use location service and then authorizes again. In this case, after this if I try to get location it gives nil though it called
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
delegate method with status 3 i.e. kCLAuthorizationStatusAuthorized.
Code to get current location :
CLLocation * location = self.locationManager.location;
Getter method :
- (CLLocationManager *)locationManager
{
if (!locationManager)
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
}
return locationManager;
}
CLLocationManager delegate method :
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
DLog(#"Location authorization changed : %d", status);
// If user has denied permission for location service
if (status == kCLAuthorizationStatusDenied)
{
DLog(#"Location service denied.");
// If authorization status changed method is already called, then SDK will not call again on same object.
// Thus, set CLLocationManager object to nil so that next time we try to get location, it will create a new object,
// and that will send message about authorization status changed.
self.locationManager.delegate = nil;
self.locationManager = nil;
}
else if (status == kCLAuthorizationStatusNotDetermined)
{
// If authorization status changed method is already called, then SDK will not call again on same object.
// Thus, set CLLocationManager object to nil so that next time we try to get location, it will create a new object,
// and that will send message about authorization status changed.
self.locationManager.delegate = nil;
self.locationManager = nil;
}
else if (status == kCLAuthorizationStatusAuthorized)
{
}
}
Any idea about this?
self.locationManager.location is nil since you never started updating the location.
In the apple docs it is stated about the location property of the locationManager:
The value of this property is nil if no location data has ever been
retrieved.
For this reason you need to somehow update your iPhones location!
Apple Docs CLLocationManager
Usually this means you want to call
[self.locationManager startUpdatingLocation]
but you can also use
[self.locationManager startMonitoringSignificantLocationChanges]
If you set the delegate to nil you will get no updates about authorization status changes, isn't it?
self.locationManager.delegate = nil;
I think you should keep the delegate in order to receive authorization status updates and then call the startUpdatingLocation method in order to get the current location.
- (void)startUpdatingLocation

CLLocationManager suddenly not asking for permission and not showing up in Privacy tab

In my app, I created a class that deals with location services. For example, I start location services like this:
- (void)startLocationServices{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
if([CLLocationManager locationServicesEnabled] == YES && [CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorized)
{
[locationManager startUpdatingLocation];
}
else {
//NSLog(#"Location services is not enabled");
//[self locationDeniedPolicy];
}}
I make my viewcontrollers subclasses of this location class if I ever needed the location of the user.
The location class itself is a subclass of UIViewController.
This used to work fine. When the user navigates to a view controller that is a subclass of this location class, it would ask for location permission for the first time. Also, the app would be listed in the privacy tab of the Settings app.
I suddenly realized that the app is no longer showing up in the Privacy tab and is not also asking for location permission. It does not use the location services at all! I have no idea why this happened? Was it an update to xcode that changed things? No idea!
Any clue?

Resources