Not being prompted to enable Location Services in App - ios

UPDATE: THIS IS NOT A DUPLICATE. I have already added the required key to the info.plist as stated in my original question and the issue remains. I have tried all three keys in various combinations.
Before anyone gets upset, I have read through many Apple Dev forum posts and stack overflow posts and cannot figure out why my app refuses to prompt the user to allow When In Use authorization.
I've added the following key to my Info.plist file with an accompanying String value:
NSLocationWhenInUseUsageDescription
I've then written (both in Swift and Obj-C) the code that should prompt the user:
#property CLLocationManager *location;
...
#synthesize location;
...
location = [[CLLocationManager alloc] init];
location.delegate = self;
location.desiredAccuracy = kCLLocationAccuracyBest;
location.distanceFilter = kCLDistanceFilterNone;
[location requestWhenInUseAuthorization];
[location startUpdatingLocation];
I'm using the following CLLocationManagerDelegate methods.
- (void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
- (void) locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
This was basically copied straight from the Apple "LocateMe" sample code.
No matter what various sequences or minor changes I try, the app never prompts to allow authorization. I've used a switch statement to determine the state of [CLLocationManager authorizationStatus], but continually recieve a "Not Determined" response.
if ([CLLocationManager locationServicesEnabled]) {
switch ([CLLocationManager authorizationStatus]) {
case kCLAuthorizationStatusAuthorizedAlways:
NSLog(#"Always Authorized");
break;
case kCLAuthorizationStatusDenied:
NSLog(#"Denied");
break;
case kCLAuthorizationStatusAuthorizedWhenInUse:
NSLog(#"Authorized in Use");
break;
case kCLAuthorizationStatusNotDetermined:
NSLog(#"Not Determined");
break;
case kCLAuthorizationStatusRestricted:
NSLog(#"Restricted");
break;
}
}
Any help would be greatly appreciated. I'm running Xcode 6.2 (6C101) with iOS 8.1.2 physical device and iOS 8.2 (12D5452a) simulator for testing.

I faced the exact same problem, after digging in for two days, it turned out that the app does not read from the info.plist file that is included in the bundle in project navigator's pane, because it has been localized to another language and base internationalization is being used, that means in Finder there will be 3 info.plist files:
1- under Tests folder
2- under base.lproj folder
3- under ar.lprj (ar refers to Arabic language).
the project reads from base.lproj's version which is not included inside the bundle in the project navigator's pane.
what I did is that I took a backup copy of the plist file that I want (number 2 above), and removed localization on the info.plist file that is inside project navigator and chose delete from disk to delete it completely, then I took the back up copy and placed in under project's root in Finder and import it back in Xcode, and now the project reads from the new info.plist file and the key NSLocationWhenInUseUsageDescription fires up the user authorization alert at app launch.
hope this helps.

If you have changed the Location Settings in your iPhone simulator this may cause the prompt to not show. For example, if you are already set the Location permissions via Allow Locations access iOS prompt and made a decision this is stored in the Privacy settings for the iPhone simulator and so subsequent calls to locationManager.requestAlwaysAuthorization() or locationManager.requestWhenInUseAuthorization() will not display the iOS prompt because you already have defined your Privacy -> Location Settings for your app.
To clear settings for an iPhone simulator: "iOS Simulator" -> "Reset Content and Settings..."
Also I did a Clean build in Xcode and quit and restarted the iPhone simulator at some point, I could be wrong about this part being of any help...

Lots of useful comparisons here: http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/
Also, silly question time: you mix _location and self.location but you don't show your property/synthesize code. Are you sure you're operating on the same object?

I found that in your info.plst file you can't use the Privacy - Location Usage Description key, you have to have a key called NSLocationWhenInUseUsageDescription and a value. I was able to get your code working by adding this key into my info.plist
#import <MapKit/MapKit.h>
#interface ViewController ()
#property CLLocationManager * location;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_location = [[CLLocationManager alloc] init];
self.location.delegate = self;
self.location.desiredAccuracy = kCLLocationAccuracyBest;
self.location.distanceFilter = kCLDistanceFilterNone;
[_location requestWhenInUseAuthorization];
[self.location startUpdatingLocation];
}

It may be silly, but i just spent almost 2 hours double and triple checking all of the answers i could find about CLLocationManager permissions.
I felt stupid when i finally realized that i had 2 info.plist files and i was using the wrong one!
You can check in your project's build settings - there's a value called Info.plist File.
Just want to leave it here for future readers.

Related

Ionic 3 - ios 11 - always ask for GPS location

For the latest ios version on the iPhone, I'm not getting the 'always' for always track your location on the iPhone. I'm getting while on the app and never. However this functionality seems to be working fine for every version previous. Any other suggestions than what I've done in XCode below would be great.
CDVLocation.m
if([[NSBundle mainBundle] objectForInfoDictionaryKey:#"NSLocationAlwaysUsageDescription"]){
[self.locationManager requestWhenInUseAuthorization];
} else if([[NSBundle mainBundle] objectForInfoDictionaryKey:#"NSLocationWhenInUseUsageDescription"]) {
[self.locationManager requestAlwaysAuthorization];
} else {
NSLog(#"[Warning] No NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription key is defined in the Info.plist file.");
}
in the plist file
<key>NSLocationAlwaysUsageDescription</key>
<string>This app requires constant access to your location in order to track your position, even when the screen is off.</string>
The code has the logic inverted, it should be this:
if ([[NSBundle mainBundle] objectForInfoDictionaryKey:#"NSLocationAlwaysUsageDescription"]){
[self.locationManager requestAlwaysAuthorization];
} else if([[NSBundle mainBundle] objectForInfoDictionaryKey:#"NSLocationWhenInUseUsageDescription"]) {
[self.locationManager requestWhenInUseAuthorization];
} else {
NSLog(#"[Warning] No NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription key is defined in the Info.plist file.");
}
Notice I switched these two lines:
[self.locationManager requestAlwaysAuthorization];
[self.locationManager requestWhenInUseAuthorization];
You can refer to the master source code.
Additionally, for iOS 11, when requesting always permission you should include the NSLocationAlwaysAndWhenInUseUsageDescription and the NSLocationWhenInUseUsageDescription key in your info plist.
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>When always is requested in iOS 11</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>When "when in use" is requested in iOS 11</string>
You are required to include the NSLocationWhenInUseUsageDescription and NSLocationAlwaysAndWhenInUseUsageDescription keys in your app's Info.plist file. (If your app supports iOS 10 and earlier, the NSLocationAlwaysUsageDescription key is also required.) If those keys are not present, authorization requests fail immediately.

Buzztouch geo location not working compiled in xcode 6

I upgraded to xcode 6, compiled a new app, discovered that the geo location is not working, and am searching for a work around.
There is no option in the phone's settings for the newly compiled app to choose a privacy/location services option "Never" or "always.
The older apps compiled in xcode5 still have this option.
UPDATE
Problem solved. Compiled in BT 3.0
- Added this code in BT_screen_customURL.m under the //appDelegate comment (line 64)
if ([appDelegate.rootLocationMonitor.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)])
[appDelegate.rootLocationMonitor.locationManager requestAlwaysAuthorization];
Added these as string messages to info.plist
NSLocationAlwaysUsageDescription
NSLocationWhenInUseUsageDescription
Additonal informaton: https://www.buzztouch.com/forum/thread.php?tid=DA308929DBC29D1DB83B7A8&currentPage=1
Also, the link provided by Alberto below was helpful.
Your app is write in Objective C?
add the following lines:
kCLAuthorizationStatusAuthorizedAlways <- For background battery-killers.
kCLAuthorizationStatusAuthorizedWhenInUse <- For sensible apps.
in your plist
For more information: http://www.splinter.com.au/2014/09/14/ios8-corelocation/
Best,
Alberto

What is the binary difference between IPA coming from AppStore and those from XCode?

Long story short:
How can I debug an iPhone-App directly on the hardware (iPhone) in exactly the same version/binary as it would be distributed by AppStore without the need to wait for AppStore-Preview-Process?
En detail:
I detected strong differences with the behaviour of an MKMapView between a compiled IPA running on an iPhone using Developer Profile via XCode/USB-Cable and between the Version installed directly from an AppStore after the Distribution-To-AppStore-Process.
I will attach two significant Screenshots.
This is how the App launches the MKMapView on an iPhone via XCode/USB-Cable pointing to the current users location with a special region:
And this is how the same App launches on the same iPhone after installing the distributed version from the AppStore without any code changes to the previous one:
Here i will provide some Code:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.mapView removeAnnotations:[self.mapView annotations]];
CLLocationCoordinate2D noLocation;
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(noLocation, 6500, 6500);
MKCoordinateRegion adjustedRegion = [self.mapView regionThatFits:viewRegion];
[self.mapView setRegion:adjustedRegion animated:NO];
mapView.delegate = self;
mapView.showsUserLocation = YES;
mapView.mapType = MKMapTypeStandard;
}
- (void)mapView:(MKMapView *)theMapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
theMapView.centerCoordinate = userLocation.location.coordinate;
}
Btw, just for your information: here occured another difference between an IPA running directly on the iPhone launched by XCode and the distributed Archive via AppStore. Without the Line "[self.mapView removeAnnotations:[self.mapView annotations]];" the App crashed directly after launch in the installed Version from AppStore, but not when running from XCode. This issue i ran into in a previous version and is not part of this question, just an addition to the main question
The main question is:
Is it possible to debug an iPhone-App exactly the same way as it would be distributed by AppStore without the need to wait for AppStore-Preview-Process, and if yes, how?
The main difference here is just likely to be a release build versus a debug build. You've got:
CLLocationCoordinate2D noLocation;
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(noLocation, 6500, 6500);
You don't set any initial value to noLocation. It's a raw struct so nobody else does either. It could have any value whatsoever. As a result adjustedRegion could be any region. No doubt it just happens to be something vaguely valid on your debug build and something completely nonsensical on your release build. Then probably MKMapView decides to show the entire earth if it can't make sense of the thing and when you shift the centre to the shops in your area it doesn't affect the zoom.
To fix, give noLocation a defined, valid value.
The version of the app you run on your iphone via Xcode will be in debug mode, the one on the App Store is in release mode. If you use preprocessors macro (like DEBUG), this could change the behaviour of your app.
If you think this could be the problem, go in XCode, in Product > Scheme > Edit Scheme, select your project's target and change the BuildConfiguration to Release. You will see how your app run in release mode even if you run it from Xcode. It will be easier to debug the behaviour of your app.

didFailWithError: Error Domain=kCLErrorDomain Code=0 "The operation couldn’t be completed. (kCLErrorDomain error 0.)"

I want to get the current location, but instead I get an error.
This is a snippet of my view controller.
- (void)viewDidLoad {
self.locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];
[locationManager setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters];
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray<CLLocation *> *)locations {
// I would get the latest location here
// but this method never gets called
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error {
NSLog(#"didFailWithError: %#", error);
}
I'm expecting the delegate method locationManager:didUpdateLocations: to get called, but instead, only locationManager:didFailWithError: gets called, and prints this:
didFailWithError: Error Domain=kCLErrorDomain Code=0 "The operation couldn’t be completed. (kCLErrorDomain error 0.)"
If you are using the simulator:
Press command + shift + , in Xcode to open the scheme editor
Select the Run scheme
Go to the Options tab
Check ✅ Allow Location Simulation
Select a Default Location in the dropdown
Selecting None as your Default Location may have caused the problem.
Check that you actually have a valid WiFi and 3G connection
...if you do, then:
Go to settings and reset your location services
Reset your network settings
This should take care of that issue. It is device/network related not app related. It's annoying especially if your app is dependent on location services and the device is WiFi only and people give negative ratings on the AppStore... Pardon me, I'm getting a bit emotional there.
Simply ignore this error and wait for more updates or a different error.
The docs for the location manager say that this error is temporary. It's letting you know that it failed to immediately retrieve a location, but it continues to try. "In such a situation, you can simply ignore the error and wait for a new event." Which is a really boneheaded way to use a method named locationManager:didFailWithError: - Thanks Apple!
Apple Documentation
Try restarting the simulator (assuming that's what you're using).
After trying everything else this worked for me.
A restart of the simulator didn't work for me.
I had to clear everything via "iOS Simulator" >> "Reset Content and
Settings....
I was getting this error on the simulator. Clicking the location button in the debugging panel and setting a location fixed the issue for me. (Ensure that the button is blue)
I have the same problem. I believe the possible explanations / fixes are covered in this SO post.
Changing the "Location" on the simulator worked for me.
Debug > Location > (Mine was checked None instead of City Bicycle Ride
e.g.)
In the simulator go to Settings > General > Reset > Reset Location & Privacy
Quit simulator and run app again
Assuming that you are using the simulator, you can to Debug -> Location and set a location.
If you have none selected you will have this error.
If you are using a custom location make sure you have the long and lat the correct way, i had it reversed and wasted 3 hours before i realised...
I have see the problem before,there is a way to solve it,but it can only work one time.If you want to run the project again and you need to repeat the solution each time.
1.In Xcode,Product -> Scheme -> Edit Scheme,then cancel the "Allow Location Simulator".
2.To the iOS Simulator and reset Content and Setting.
3.Again to the Xcode,repeat the first step.
4.To the iOS Simulator and reset. Then it will work.
If you are using the Simulator, make sure the scheme allows location, and you picked a default location.
Issues like this can be resolved by setting location as "Apple". At least it works for testing purpose.
I have reseted contents and settings.
Removed data from derived data.
Restarted the Xcode, and Simulator and worked for me.
from the answer of #Mem and many others thanks
For returned devs :) Just select "Debug->Location->Freeway Drive" from the Simulator menu. If still problem then try after doing "Simulator->Reset Content and Settings" form the simulator menu. This helped me once with the same issue. Some time simulator location is set to "Custom location" due to which its not detecting anything.
Try in device. Sometimes simulator fails to take your location.
Go to home in simulator
home ->Settings ->Privacy ->Locations -> select the app and choose always
when adding permission Privacy - Location When In Use Usage Description in the info.plist it was solved for me

Core Location in iPhone Simulator 3.2 (iPad)

So,
i'm trying to port my app to iPad.
I'm using CoreLocation.
Apple says the iPad does have
Location:
Wi-Fi
Digital compass
Assisted GPS (Wi-Fi + 3G model)
Cellular (Wi-Fi + 3G model)
so it should be possible to get the position of my ipad (at least with 3g model) about 3km radius would be enought.
but it doesnt work in simulator (3.2 ipad) (running 3.1.3 in simulator simulates me cupertino).
is there a way to get the position in simulator (3.2 ipad) ?
i live in germany and here the ipad isnt released yet, so i cannot test it on my device.
thanks!
edit
thats how i'm trying to get my connection
locationManager = [[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
locationManager.delegate = self;
[locationManager startUpdatingLocation];
and always on 3.2 locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error gets called. not on 3.1.3
error object looks like this:
Error Domain=kCLErrorDomain Code=0 "Operation could not be completed. (kCLErrorDomain error 0.)"
edit
so i handled it something like this:
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
#ifdef TARGET_IPHONE_SIMULATOR
// Cupertino
CLLocation *simulatorLocation = [[CLLocation alloc] initWithLatitude:37.33168900 longitude:-122.03073100];
[self locationManager:locationManager didUpdateToLocation:simulatorLocation fromLocation:nil];
[simulatorLocation release];
#else
[[NSNotificationCenter defaultCenter] postNotificationName:#"ErrorNotification" object:NSLocalizedString(#"GPS-coordinates could not be detected",#"")];
#endif
}
It is very messy but works.
edit2: try enabling your Airport, this could also solve the problem!!
Yes, see this question which has several good answers to this.
EDIT - I eventually decided to write my own CLLocationManager simulator for testing on the iPhone simulator. It's located on github here if you want to use it.
According to the iPhone Development Guide, the location in the simulator is fixed. Sorry!
You might also wanna check out my FTLocationSimulator.
It reads a KML file generated by Google Earth to provide continuous location updates. It also updates the blue userLocation dot in a MKMapView with the simulated location updates.

Resources