38

I'm trying to use the CLLocationManager framework in my iOS project to access the user's location but when I call

[locationManager startUpdatingLocation]

neither locationManager:didUpdateLocations: or locationManager:didFailWithError: are getting called.

//myViewController.h
@interface myViewController : UITableViewController <CLLocationManagerDelegate>
@end

//myViewController.m
@implementation myViewController{
    CLLocationManager *locationManager;
}

//edit
- (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
}
//finish edit

-(void)getLocation
{
    locationManager.delegate = self;
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    [locationManager startUpdatingLocation];
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
UIAlertView *errorAlert = [[UIAlertView alloc]
                           initWithTitle:@"Error" 
                                 message:@"Failed to Get Your Location"              
                                delegate:nil 
                       cancelButtonTitle:@"OK" 
                      otherButtonTitles:nil];
[errorAlert show];
}

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    CLLocation *newLocation = locations[[locations count] -1];
    CLLocation *currentLocation = newLocation;
    NSString *longitude = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude];
    NSString *latitude = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude];

if (currentLocation != nil) {
   NSLog(@"latitude: %@", latitude);
   NSLog(@"longitude: @"%@", longitude);
}else {
    UIAlertView *errorAlert = [[UIAlertView alloc]
                               initWithTitle:@"Error" message:@"Failed to Get Your Location" 
                                                     delegate:nil 
                                            cancelButtonTitle:@"OK" 
                                            otherButtonTitles:nil];
    [errorAlert show];
}

}
@end

Neither delegate method is being called despite what it says in the documentation:

"This method returns immediately. Calling this method causes the location manager to obtain an initial location fix (which may take several seconds) and notify your delegate by calling its locationManager:didUpdateLocations: method [...] In addition to your delegate object implementing the locationManager:didUpdateLocations: method, it should also implement the locationManager:didFailWithError: method to respond to potential errors."

Don't know how to debug the issue.

Thanks,

JA

Mihir Oza
  • 2,768
  • 3
  • 35
  • 61
ja.
  • 467
  • 1
  • 5
  • 16
  • Is `getLocation` called? Did you looked for `locationServicesEnabled` returns or `authorizationStatus` returns? – Larme Sep 18 '14 at 15:36
  • yes, `get location` is called. Not totally sure what you mean by `locationServicesEnabled`. What should `locationManager:didChangeAuthorizationStatus` return? – ja. Sep 18 '14 at 15:41
  • 2
    did yo initialize location manager. [[CLLocationManager alloc] init] – meth Sep 18 '14 at 15:41
  • Yea in `viewDidLoad` sorry I forgot to include that – ja. Sep 18 '14 at 15:43
  • 1
    Are you using simulator? If so, this has been asked way too many times on StackOverflow – taylorcressy Sep 18 '14 at 15:49
  • No I'm running it on a device. – ja. Sep 18 '14 at 15:51
  • Were you ever prompted for location services? Did you select yes? Does it show up in Settings on the device? – taylorcressy Sep 18 '14 at 15:52
  • I added the line `[locationManager requestWhenInUseAuthorization]; ` at the beginning of the `getLocation` method but it still doesn't prompt me... – ja. Sep 18 '14 at 16:40
  • if you are using ios 8, look at this http://stackoverflow.com/questions/24062509/ios-8-location-services-not-working – Nik Yekimov Sep 19 '14 at 03:15
  • Ah, @taylorcressy that is driving me crazy. I am using the simulator, so a link to where it was already asked would be helpful. Thanks! – Jay Imerman Jul 14 '15 at 00:42

8 Answers8

89

enter image description hereJust add this in info.plist

NSLocationAlwaysUsageDescription --- I need Location

NSLocationWhenInUseUsageDescription --- I need Location

privacy - location usage description --- I need Location

Note that "I need Location" should be changed to describe your actual app's designed usage. It is communicated to the end user in the authorization message. (thanks @devios1)

  locationManager = [[CLLocationManager alloc] init];
  locationManager.delegate=self;
  locationManager.desiredAccuracy=kCLLocationAccuracyBest;
  locationManager.distanceFilter=kCLDistanceFilterNone;
  [locationManager requestWhenInUseAuthorization];
  [locationManager startMonitoringSignificantLocationChanges];
  [locationManager startUpdatingLocation];

Now it will call your didUpdateToLocation definitely.

for more details click here

Mohit Tomar
  • 5,173
  • 2
  • 33
  • 40
  • 14
    Note that "I need Location" should be changed to describe your actual app's designed usage. It is communicated to the end user in the authorization message. – devios1 Jan 12 '15 at 19:54
  • 2
    Is it normal to start significant monitoring with standard location updates? Or are you supposed to pick one of the two? – Myxtic Mar 09 '15 at 16:06
  • 1
    Was struggling with this until I saw your answer. This: NSLocationWhenInUseUsageDescription --- I need Location saved me. Thanks man – saintjab Sep 25 '15 at 17:09
  • @Mohit tomar, hello sir method is not called yet in my app, i already add the keys in my plist file – sandeep tomar Jan 16 '16 at 12:09
  • Check Location permission for your app in settings. – Mohit Tomar Jan 30 '16 at 06:24
  • Hi, **[locationManager requestWhenInUseAuthorization];** is very important Line. – Anup Gupta Jan 24 '18 at 10:23
  • How many apps *really* need 'always'? I tend to allow apps to know my location only 'when in use'. – clearlight Apr 06 '22 at 23:00
19

You strongly need to check that you initialize CLLocationManager on main thread. In other case you will not get updateLocation event.

I can't find such info in Apple docs but it works for me anyway.

malex
  • 9,874
  • 3
  • 56
  • 77
  • Thank you so much, this was my issue! Also beware that for me, I would receive updateLocation events using the simulator, but not on the device.. perhaps because of architecture differences. Cheers! – Randoramma Apr 04 '18 at 22:06
  • 3
    location manager requires to have run loop. You can have in on background thread as long as that thread has run loop. So for background thread you need to create run loop yourself. – Juraj Antas Jan 17 '19 at 21:43
  • 1
    Unbelievable! Just spent some hours figuring out, why locationmanager is not firing events (on macOS), but I did everything right, I was just not on the ui-thread. Thanks for this info. – Tom Sep 18 '19 at 10:53
13

Location Services work a bit differently starting in iOS 8.

Mainly, you need to add a key NSLocationWhenInUseUsageDescription to your Info.plist file, and add a description why your app need Location, such as "Location needed to ...".

Note that you might also have to check for iOS version. Only iOS 8 and up have the Location Manager listen to the requestWhenInUseAuthorization call.

The link below shows more details: http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/

Good luck!

  • great!.. the link that you describe above "http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/" was really helpful – Pablo Pantaleon Dec 05 '14 at 05:29
  • Link is very helpful. – AKG Dec 19 '14 at 11:32
  • NSLocationWhenInUseUsageDescription was the key, i wasted 2 hours finding this little knob, the String you put in there is presented to the end user as a reason why you need access to the current location. – Klajd Deda Jun 05 '17 at 19:59
5

With iOS 8.0 you need to call -[CLLocationManager requestWhenInUseAuthorization ] or -[CLLocationManager requestAlwaysAuthorization] first so the user gets asked to give your app permission to use the location.

orkoden
  • 18,946
  • 4
  • 59
  • 50
  • 1
    I added the line [locationManager requestWhenInUseAuthorization]; at the beginning of the getLocation method but it still doesn't prompt me... – ja. Sep 18 '14 at 16:44
  • go to your phone's settings->privacy->location services and make sure it's On, then see what options you have for your app. if it's been denied at some point, the app will never prompt again. – mitrenegade Sep 19 '14 at 05:56
  • 1
    Try this one [CLLocationManager authorizationStatus] – Kamleshwar Jul 11 '16 at 19:20
4

You need to add below things to your project,

  1. In plist of your project add these things:

    1. Key: NSLocationAlwaysUsageDescription Type:String
    2. Key: NSLocationWhenInUseUsageDescription Type:String
  2. In the .m file with [locationManager startUpdatingLocation] add this condition :

    if([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
         [locationManager requestAlwaysAuthorization];`
    

Then only your CLLocationManager delegate methods will get called.

Michaël Azevedo
  • 3,874
  • 7
  • 31
  • 45
1

I think you should check this link.You are not retaining the location manager object when declaring.

please give property to you object @property(nonatomic, strong)

Why the CLLocationManager delegate is not getting called in iPhone SDK 4.0?

Community
  • 1
  • 1
Dheeraj Kumar
  • 490
  • 3
  • 12
1

So if you are running in simulator don't forget to set location in simulator menu. It looks like if it is set to none nothing is called in delegate... I am not sure than if this can happen on real device too but probably it's simulator specific.

Renetik
  • 5,887
  • 1
  • 47
  • 66
0

I had the following in my code base:

-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
    if( status == kCLAuthorizationStatusAuthorizedAlways ) {
        _locationManager = [[CLLocationManager alloc] init];
        _locationManager.delegate = self;
        _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
        _locationManager.distanceFilter = 200;
    }
}

Turns out that this was getting called in an infinite loop, because initializing a locationManager triggers this method for some reason? I had not realized that. I had put it there to catch when permissions were granted. Instead, I set up a location manager and started updating the location, but then this fired and replaced it with one that wasn't updating the location, and kept looping over and over.

Solution for me was just to add && !_locationManager to the if condition.

Jake T.
  • 4,308
  • 2
  • 20
  • 48