Spent few days trying to solve this but unable to find any solutions that works. I have checked all the post on stackoverflow and tried all their solutions and nothing seems to be working for. I have also tried the apple test project for CLLocation which works fine for me. I used bits and pieces from the apple test project
https://developer.apple.com/library/ios/samplecode/LocateMe/Listings/README_md.html
But my code is not working at all. The DidupdateToLocation never gets called.
Here is my code (in viewDidLoad)
_locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
// This is the most important property to set for the manager. It ultimately determines how the manager will
// attempt to acquire location and thus, the amount of power that will be consumed.
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// Once configured, the location manager must be "started"
//
// for iOS 8, specific user level permission is required,
// "when-in-use" authorization grants access to the user's location
//
// important: be sure to include NSLocationWhenInUseUsageDescription along with its
// explanation string in your Info.plist or startUpdatingLocation will not work.
//
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
[self performSelector:#selector(stopUpdatingLocationWithMessage:)
withObject:#"Timed Out"
afterDelay:30];
I have checked to make sure locationServicesEnabled is enabled.
I have added NSLoationWhenInUseUsageDescription property to the info.plist file. Is there any other property I need to add or enable any services??
I cannot for the love of god figure out what i have done wrong. Can some one please help me with this.
You have to call the startUpdatingLocation after you received the didChangeAuthorizationStatus callback on iOS8.
//iOS 8 API change
if([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]){
[self.locationManager requestWhenInUseAuthorization];
}else{
[self.locationManager startUpdatingLocation];
}
implement this delegate method:
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
switch (status) {
case kCLAuthorizationStatusNotDetermined:
case kCLAuthorizationStatusRestricted:
case kCLAuthorizationStatusDenied:
{
// do some error handling
}
break;
default:{
[self.locationManager startUpdatingLocation];
}
break;
}
}
First, don't forget, with IOS 8 you need to do [locationManager requestWhenInUseAuthorization] plus [locationManager requestAlwaysAuthorization];
_locationManager = [CLLocationManager new];
if(SYSTEM_IS_OS_8_OR_LATER) {
[_locationManager requestWhenInUseAuthorization];
[_locationManager requestAlwaysAuthorization];
}
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
//and the problem with your code : don't forget to start
_locationManager startUpdatingLocation];
and in your didUpdateLocations
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
_currentLocation = [locations objectAtIndex:0];
//do your stuff with the location
}
Silly me. I added the keywords to the wrong plist file. I have got it working now. Thanks for your help guys.
I just spend an entire morning on this [in honestly I am relative new OOC], anyway the problem..
didUpdateLocation compiles and is never called
didUpdateLocations compiles and does work!!
Not the answer in this case it would seem, but it is in the question, an easy mistake to make. Using IOS 8.1.3 & Xcode 6.1.1
Simply add three properties in Info.plist.
To get the current location, if it is not calling didUpdateToLocation method
NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
privacy - location usage description of type String.
Related
I have an app that uses background location updates, it needs to constantly track the devices position regardless if the app is in the foreground or background. I have the background tracking setup in the app delegate.
In the front end I have a single UIViewController with a working mapkit view all the CCLocationManager code triggers without error but didUpdateUserLocation is never fired within the custom UIViewController class.
Background location tracking is working with absolutely no problems.
Here is the code i'm using in viewDidLoad
[self.mapView setShowsUserLocation:YES];
[self.mapView setShowsPointsOfInterest:YES];
self.locationManager = [[CLLocationManager alloc] init];
[self.locationManager requestWhenInUseAuthorization];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
[self.locationManager setDelegate:self];
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
NSString *error;
if (![CLLocationManager locationServicesEnabled]) {error = #"Error message";}
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
if (status == kCLAuthorizationStatusRestricted || status == kCLAuthorizationStatusDenied) {error = #"Error message";}
if (error) {NSLog(error);}
else
{
status = [CLLocationManager authorizationStatus];
self.locationManager.pausesLocationUpdatesAutomatically = NO;
self.locationManager.activityType = CLActivityTypeAutomotiveNavigation;
[self.locationManager stopMonitoringSignificantLocationChanges];
[self.locationManager startUpdatingLocation];
}
Any help would be appreciated
Thanks
You need to check below details:
Testing this on simulator?? didUpdateLocations must be tested on real device.
Make sure that you specified the NSLocationAlwaysUsageDescription string or else the app won't present the authorization message, and you won't be authorized.
Have you implemented locationManager:didFailWithError:? did you got any error?
Have you implemented locationManager:didChangeAuthorizationStatus:? Are you getting this called with a successful authorization status?
I worked out the problem finally.
Turns out even if you're using the location stuff in Schema and Xcode you still need to set it in the Simulator via Debug > Location
Hopefully this helps someone else.
and now, with iOS 9, the following needs to be included for any update;
if ([ locationManager respondsToSelector:#selector(requestWhenInUseAuthorization )])
{
locationManager.allowsBackgroundLocationUpdates = YES;
}
Else background updates will be impaired.
Since I updated to iOS SDK 8 and 8.1, there have been many problems, including that the method of CLLocationManager didUpdateLocations is no longer called.
Here the code:
In viewDidLoad:
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
[locationManager requestAlwaysAuthorization];
}
[locationManager startUpdatingLocation];
The method:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{ NSLog(#"Call?"); }
A couple of thoughts:
Are you testing this on simulator or on device? You must test this on actual device. FWIW, didUpdateLocations works fine on my iOS 8.1 device.
Make sure that you specified the NSLocationAlwaysUsageDescription string or else the app won't present the authorization message, and you won't be authorized.
Obviously, if you don't need "always usage", you should just requestWhenInUseAuthorization and then you must specify NSLocationWhenInUseUsageDescription string.
Have you checked [CLLocationManager authorizationStatus]? I do that before I even try to authorize or start location services, because if it's either kCLAuthorizationStatusDenied or kCLAuthorizationStatusRestricted, the location services won't work until the user goes to settings and remedies that. You may want to present them a message to that effect if you get either of these authorization codes.
Have you implemented locationManager:didFailWithError:? Does it report anything?
Have you implemented locationManager:didChangeAuthorizationStatus:? Are you getting this called with a successful authorization status?
Need include MapKit.framework from Capabilities:
I had the same problem, and my code (viewdidupdate method) was missing this:
_mapView.delegate = self;
For some reason the app worked in ios 7 without the line, but in ios 8.1 didUpdateUserLocation was never called.
Specify both NSLocationAlwaysUsageDescription and NSLocationWhenInUseUsageDescription in your plist:
Also in code, request authorization:
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) { // or requestAlwaysAuthorization
[self.locationManager requestWhenInUseAuthorization]; // or requestAlwaysAuthorization
}
[self.locationManager startUpdatingLocation];
I'm asking this because I'm a bit confused. I did set NSLocationAlwaysUsageDescription in my Info.plist and this is the code I'm running:
CLLocationManager *locMan = [[CLLocationManager alloc] init];
locMan.delegate = self;
if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedAlways)
{
[locMan requestAlwaysAuthorization];
}
[locMan startUpdatingLocation];
I set a breakpoint and verified that this does indeed get called, but I am not alerted in the app. I check in my privacy settings and saw the app had an entry with the two options: None and Always, with neither checked. I tried to uninstall, clean, and reinstall, but still is not working. Any ideas?
EDIT:
I moved the above block from viewDidLoad into viewDidAppear: and now the alert comes up and disappears half a second later
I solved my issue. It's a retain issue. I was declaring my CLLocationManager locally, so when it reached the end of my method, it would didn't exist anymore, which explains why it couldn't ask for permission. I promoted it to be a property and now all works well
You need to add this line at the end of your code
[self.locationManager startUpdatingLocation];
What about if you try this:
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
if ([locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[locationManager requestWhenInUseAuthorization];
}
[locationManager startUpdatingLocation];
Sorry, missread your post. Maybe try this:
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status == kCLAuthorizationStatusDenied) {
// Show alert or something
}
else if (status == kCLAuthorizationStatusNotDetermined) {
[self.locationManager requestAlwaysAuthorization];
}
More can be read here: Core Location Manager Changes in iOS 8
I am having a lot of trouble after updating to iOS 8. The following code worked before I updated to iOS and Xcode 6. Code is written inside viewDidLoad:
self.locationManager.delegate = self;
[self.locationManager requestWhenInUseAuthorization];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];
In my .h file, I have locationManager as a property, also declaring CLLocationManagerDelegate:
#property CLLocationManager *locationManager;
I've set a breakpoint inside
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
but the code never ran.
What step am I missing???
EDIT: do note that the prompt asking the user to allow location services never appeared. I suspect that this is the issue but I did request the service right after I declared the delegate to self.
Also added
<key>NSLocationWhenInUseUsageDescription</key>
<string>Your message goes here</string>
But still does not work for me
if you start location before user agree to use location server
ios8 or later change to
- (xx)xxxx
{
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways) {
[self.locationManager startUpdatingLocation];
}else{
[self.locationManager requestWhenInUseAuthorization];
}
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
if([CLLocationManager authorizationStatus] != kCLAuthorizationStatusNotDetermined){
[self.locationManager startUpdatingLocation];
}
}
You need to add NSLocationWhenInUseUsageDescription key to your info.plist. (From my testing, it can be an empty string, but the key must exist. Not sure if Apple fails review for empty string, though.)
You need to use requestAlwaysAuthorization (for background location) or requestWhenInUseAuthorization (location only when foreground) call on CLLocationManager is needed before starting location updates.
There also needs to be NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription key in Info.plist with a message to be displayed in the prompt.
More information in this post: Location Services not working in iOS 8
So after all the "iOS 8" issues, I realized my problem was that I didn't allocate and init my locationManager
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
[self.locationManager requestWhenInUseAuthorization];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways) {
[self.locationManager startUpdatingLocation];
}else{
[self.locationManager requestWhenInUseAuthorization];
[self.locationManager requestAlwaysAuthorization];
}
[self.locationManager startUpdatingLocation];
Basically half the time the delegate method
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations;
is not called at all. But the other half of the time it works perfectly! I've found that it usually happens when I first start up Xcode after closing and quitting it, but then after that or a couple runs after that it seems to work fine. I'm not 100% sure if it's just an Xcode problem or what, I'll be getting a developer's license soon so I'll see if it will work fine on an actual device.
Starting from the viewDidAppear (tried in viewDidLoad also, made no difference), I run a method to init my locationManager stuff:
locationManager = [[CLLocationManager alloc]init];
[locationManager setDelegate:self];
locationManager.distanceFilter = 20.0f;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.pausesLocationUpdatesAutomatically = NO;
if ([locationManager respondsToSelector:#selector(requestAlwaysAuthorization)])
[locationManager requestAlwaysAuthorization];
[locationManager startUpdatingLocation];
Sometimes this works, sometimes it doesn't. I even made a timer to re-run this every so-and-so seconds, and this doesn't work.
Is there something else I should do? Is there any answer to this problem?
Thanks.
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations;
This delegate method is invoked only if new locations are available. Sometimes gps will not get satellite signal hence locations cannot be obtained. So in these situations the above mentioned method will not get triggered. Since you are testing in simulator,you should change or set the location. I think it will work fine on an actual device.
add in viewdidappear
_locamangr = [CLLocationManager new];
_locamangr.delegate = self;
// _locamangr.distanceFilter = kCLDistanceFilterNone;
_locamangr.desiredAccuracy = kCLLocationAccuracyBest;
if ([_locamangr respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[_locamangr requestAlwaysAuthorization] ;
[_locamangr requestWhenInUseAuthorization];
}
[_locamangr startUpdatingLocation];
and set in infoplist.
NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription