didChangeAuthorizationStatus is run when authorization is not changed - ios

I have created a button. When the button is clicked I want to get my location. I have to ask user for permission before I will use location manager. Please look at my code:
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) {
[self startGettingLocation];
}
}
- (IBAction)locationButtonAction:(id)sender {
if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) {
[self startGettingLocation];
} else if (status == kCLAuthorizationStatusNotDetermined) {
[self.locationManager requestWhenInUseAuthorization];
}
}
The problem is that the method locationManager:didChangeAuthorizationStatus is run after view did load too! Method startGettingLocation is started when the user doesn't click button. How to change this code to run startGettingLocation only when user clicks on button.

- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.initialAuthorizationStatus = [CLLocationManager authorizationStatus];
self.locationManager = [CLLocationManager new];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
// If status really did change.
if (self.initialAuthorizationStatus != status) {
if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) {
[self startGettingLocation];
}
}
}
- (IBAction)locationButtonAction:(id)sender {
if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) {
[self startGettingLocation];
} else if (status == kCLAuthorizationStatusNotDetermined) {
[self.locationManager requestWhenInUseAuthorization];
}
}

Related

Location Services Stop working after reinstall with iOS10

Location services stopped working after I uninstalled my iOS10 app. I have the description set up in the Info.plist so it confuses me why location services would stop working. The app does not show up in Settings->Privacy->Location Services
<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs to use your location so that it may send it to your selected contacts.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs to use your location so that it may send it to your selected contacts.</string>
Checking for status using the following code reveals that the status is Not Determined.
if ([CLLocationManager locationServicesEnabled]) {
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusRestricted) {
NSLog(#"RESTRICTED");
} else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
NSLog(#"DENIED");
} else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) {
NSLog(#"NOT DETERMINED");
} else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways) {
NSLog(#"ALWAYS");
} else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse) {
NSLog(#"WHEN IN USE");
}
}
EDIT:
The viewController viewDidLoad method contains the following code:
- (void)viewDidLoad {
[self.locationManager requestAlwaysAuthorization];
[self.locationManager requestWhenInUseAuthorization];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.delegate = self;
if ([CLLocationManager locationServicesEnabled]) {
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusRestricted) {
NSLog(#"RESTRICTED");
} else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
NSLog(#"DENIED");
} else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) {
NSLog(#"NOT DETERMINED");
} else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways) {
NSLog(#"ALWAYS");
} else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse) {
NSLog(#"WHEN IN USE");
}
}
}
You need to use [yourLocationManager startUpdatingLocation] which will prompt the alert for Using location.
Until then authorizationStatus will be kCLAuthorizationStatusNotDetermined
Edit
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager requestAlwaysAuthorization];
self.locationManager.delegate = self;
Add this
You need to check authorization status, and if it's xxx, you need to call requestAlwaysAuthorization() or requestWhenInUseAuthorization(). That will trigger an alert to the user.
If you've deleted the app by long-pressing the app icon and tapping the X, that revokes the user's permission to use location services, so the app will be denied access until you call requestAlwaysAuthorization() or requestWhenInUseAuthorization() again.

How to solve the issue with beacon?

My Problem: When I click the button, my phone will show a progress view(ask me come close the beacon), and when I come close the beacon, my phone will show a view(checkmark), and then remove the view 1.5s later. Now the view can show normally first, but when I take my phone far away from the beacon, and the view(show checkmark) will show 1s later. It's a big problem out of my mind.
My code:
onClick button
- (IBAction)chooseBLEAction:(id)sender {
self.locationManager = [CLLocationManager new];
[self _initBeaconRegion];
if (([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse ||
[CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways ||
[CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) &&
[self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)])
{
[self _start];
if (self.bluetoothIsOpen) {
[self _createProgressView];
}
}else {
[self.locationManager requestWhenInUseAuthorization];
}
}
- (void)_start {
[self.locationManager startRangingBeaconsInRegion:self.targetBeaconRegion];
}
- (void)_stop {
[self.locationManager stopRangingBeaconsInRegion:self.targetBeaconRegion];
}
CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray<CLBeacon *> *)beacons inRegion:(CLBeaconRegion *)region {
NSLog(#"searching for beacon !");
CLBeacon *foundBeacon = [CLBeacon new];
foundBeacon = [beacons firstObject];
if (foundBeacon) {
NSLog(#"found beacon !");
switch (foundBeacon.proximity) {
case CLProximityUnknown:
break;
case CLProximityFar:
break;
case CLProximityNear:
break;
case CLProximityImmediate:
{
[self _stop];
NSLog(#"Immediate beacon !");
AudioServicesPlaySystemSound(1051);
[self.myProgressView removeFromSuperview];
[self _createSuceessProgressView];
self.removeProgressViewTimer = [NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:#selector(_removeSuccessProgressView) userInfo:nil repeats:NO];
break;
}
}
}
}
create progress view (close the beacon)
- (void)_createProgressView {
NSString *title = #"Please close the beacon";
self.myProgressView = [MRProgressOverlayView showOverlayAddedTo:self.view title:title mode:MRProgressOverlayViewModeIndeterminate animated:YES];
}
create success view
- (void)_createSuceessProgressView {
NSString *title = #"Success!";
self.suceessProgressView = [MRProgressOverlayView showOverlayAddedTo:self.view title:title mode:MRProgressOverlayViewModeCheckmark animated:YES];
}
remove success view 1.5s later
- (void)_removeSuccessProgressView {
[self.removeProgressViewTimer invalidate];
[self.suceessProgressView removeFromSuperview];
}

App crashing (Location GPS Region Monitoring)

App crashes on launch in Xcode: it does not generate a bug report, and instead terminates during a thread (self > UIViewController > _locationManager).
Below is the code from MapViewController.m
#import "MapViewController.h"
#interface MapViewController ()
#end
#implementation MapViewController
- (void)viewDidLoad {
[super viewDidLoad];
//Monitoring a Region
[self.locationManager requestWhenInUseAuthorization];
[self.locationManager startUpdatingLocation];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)initializeLocationServices
{
NSLog(#"Started location services");
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.distanceFilter = kCLDistanceFilterNone;
_locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
_locationManager.pausesLocationUpdatesAutomatically = NO;
[_locationManager startUpdatingLocation]; // to show authorisation popup
}
-(CLCircularRegion*)createRegion
{
// Test coordinates
CLLocationDegrees latitude = 50;
CLLocationDegrees longitude = -1;
CLLocationDistance radius = 50; // meters;
// If radius is too large, registration fails automatically, so limit the radius to the maximum value
if (radius > _locationManager.maximumRegionMonitoringDistance) {
radius = _locationManager.maximumRegionMonitoringDistance;
}
CLCircularRegion* region = [[CLCircularRegion alloc] initWithCenter:CLLocationCoordinate2DMake(latitude, longitude) radius:radius identifier:#"Clue1"];
region.notifyOnEntry = YES;
region.notifyOnExit = YES;
NSLog(#"Created region");
return region;
}
-(void)monitorProximity
{
CLRegion *region = [self createRegion];
// Check if support is unavailable
if ( ![CLLocationManager isMonitoringAvailableForClass:[CLRegion class]]) {
NSLog( #"Failed to initialise region monitoring: support unavailable");
return;
}
// Check if authorised
if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedAlways) {
NSLog( #"Failed to initialise region monitoring: app not authorized to use location services");
return;
} else {
NSLog(#"Started monitoring proximity");
}
// Clear out any old regions to prevent buildup.
if ([_locationManager.monitoredRegions count] > 0) {
for (id obj in _locationManager.monitoredRegions)
[_locationManager stopMonitoringForRegion:obj];
}
[_locationManager startMonitoringForRegion:region];
}
-(void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region
{
NSLog(#"Started monitoring for region: %#", [region description]);
//[_locationManager requestStateForRegion:region]; // check if already inside region
}
-(void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error
{
NSLog(#"Failed to start monitoring for region: %#", [error localizedDescription]);
}
-(void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
NSLog(#"didDetermineState");
if (state == CLRegionStateInside) {
//println(#"Enter");
NSLog(#"inside");
return;
} else if (state == CLRegionStateOutside) {
// println(#"Outside");
NSLog(#"outside");
} else {
// println("unknown");
NSLog(#"unknown");
}
}
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
NSLog(#"didEnterRegion");
}
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
NSLog(#"didExitRegion");
}
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
NSLog(#"Monitoring authorisation status is now: %#", status == kCLAuthorizationStatusAuthorizedAlways ? #"authorized" : #"not authorized");
if (status == kCLAuthorizationStatusAuthorizedAlways) {
[self monitorProximity];
}
}
#end
UPDATE: Where do I put Initialise call for locationManager and also associate with MapKit map? App won't launch as thread fails.

Location manager is not working in iOS8

Please don't mark it as duplicate because I took help from others posted answer in stack overflow. But still I faced some issues. Location manager delegate not get called even in real device also. And also it's not asking for the permission.
Below is my code.
- (IBAction)getUserLocationAction:(id)sender
{
if([CLLocationManager locationServicesEnabled])
{
if(!locationManager)
locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
if ([locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[locationManager requestWhenInUseAuthorization];
}
[locationManager startUpdatingLocation];
//[locationManager startMonitoringSignificantLocationChanges];
}
else
{
NSLog(#"Location service is not enabled");
}
}
#pragma mark - Location Manager Delegate-
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(#"%#", locations);
userLocation = [locations lastObject];
NSLog(#"User Current Locatiion\nLat: %+.6f\nLong: %+.6f", [userLocation coordinate].latitude, [userLocation coordinate].longitude);
[locationManager stopUpdatingLocation];
//[locationManager stopMonitoringSignificantLocationChanges];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"Error: %#", [error localizedDescription]);
}
I also add the below two key in my .plist file
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app want to use your location</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app want to use your location</string>
I have also added the frameworks
I am not sure where I am doing wrong. Please help me.
UPDATE
Firstly I think its an issue with my code but after some research it's working as expected in iOS7. The code is remain same, this issue occur only in iOS8. Please let me know what changes needs to be done for working in iOS8 also.
You need to do some more checking:
- (IBAction)getUserLocationAction:(id)sender
{
if([CLLocationManager locationServicesEnabled]) {
if(!self.locationManager) {
self.locationManager = [[CLLocationManager alloc] init];
[self.locationManager setDelegate:self];
[self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
}
CLAuthorizationStatus authStatus = [CLLocationManager authorizationStatus];
if (authStatus == kCLAuthorizationStatusNotDetermined) {
// Check for iOS 8 method
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
else {
[self.locationManager startUpdatingLocation];
}
}
else if(authStatus == kCLAuthorizationStatusAuthorizedAlways || authStatus == kCLAuthorizationStatusAuthorizedWhenInUse || authStatus == kCLAuthorizationStatusAuthorized) {
[self.locationManager startUpdatingLocation];
}
else if(authStatus == kCLAuthorizationStatusDenied){
NSLog(#"User did not allow location tracking.");
// present some dialog that you want the location.
}
else {
// kCLAuthorizationStatusRestricted
// restriction on the device do not allow location tracking.
}
}
else {
NSLog(#"Location service is not enabled");
}
}
Also you need to handle the use callback:
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status != kCLAuthorizationStatusRestricted && status !=kCLAuthorizationStatusDenied) {
[self.locationManager startUpdatingLocation];
}
}
Check your Location Access settings..so go to Setting-->Privacy-->Location Services-->Your app

CoreLocation not working in ios 8

I'm using Location service in my app.
But [CLLocationManager authorizationStatus] is kCLAuthorizationStatusNotDetermined both before [self.locationManager startUpdatingLocation];
code of project:
Implementation
#import <CoreLocation/CoreLocation.h>
#interface NewRunViewController () <CLLocationManagerDelegate>
#property (nonatomic, strong) CLLocationManager *locationManager;
- (void)viewDidLoad
{
[super viewDidLoad];
[self startLocationUpdates];
}
- (void)startLocationUpdates
{
// Create the location manager if this object does not
// already have one.
if (self.locationManager == nil) {
self.locationManager = [[CLLocationManager alloc] init];
}
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = 10;
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
}
I also add NSLocationWhenInUseUsageDescription key into info.plist file.
And app also does not ask for user permission to use core location service.
Can anyone help me??
You must include a string value for the key NSLocationAlwaysUsageDescription for your target.
Look on the Info page of your target in Xcode. The string will be the text for the alert when the system asks the user for permission to use location services in your app.
This is my own code for handling same. It is requesting Always Authorization but you could replace with When in Use.
CLAuthorizationStatus auth = [CLLocationManager authorizationStatus];
if (auth == kCLAuthorizationStatusNotDetermined && [self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[self.locationManager performSelector:#selector(requestAlwaysAuthorization) withObject:NULL];
} else {
if (auth == kCLAuthorizationStatusAuthorizedAlways) {
[self notificationsSetup];
} else {
NSLog(#"Device is not authorized for proper use of the location Services, no logging will be performed");
}
}
You might find my github repository helpful- TTLocationHandler on Githup
you have to move
[self.locationManager startUpdatingLocation];
to the delegate method
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
case kCLAuthorizationStatusNotDetermined:
{
NSLog(#"User still thinking");
}
break;
case kCLAuthorizationStatusDenied:
{
NSLog(#"User denied location request");
}
break;
case kCLAuthorizationStatusAuthorizedWhenInUse:
case kCLAuthorizationStatusAuthorizedAlways:
{
[self.locationManager startUpdatingLocation];
}
break;
default:
break;
}
}
Update : Make the log easier to be understood
Thank you guys for your answers. I found solution of problem. I checked the version of system like:
#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
in startLocationUpdates method:
if(IS_OS_8_OR_LATER) {
if ([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[self.locationManager requestAlwaysAuthorization];
}
}
Now it's working properly.

Resources