Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

iOS Build a Diary App Using Core Data Custom Detail View Controller Using Core Location

CLLocationManager doesn't store location

Hi all,

I've followed the video and been through it again to make sure I didn't miss anything but I can't get entry.location to equal anything other than null.

I have inserted some NSLog lines to see which bits of code are being reached, and which aren't.

This shows me that in viewDidLoad of the EntryViewController.m the line,

[self.locationManager startUpdatingLocation];

does get reached. The callback never happens as the NSLog I placed inside -(void)locationManager:(CLLocationManager *)manager didUpdateLocations: never appears in the log so the GPS simulation doesn't call that code.

In the EntryCell.m code, the self.locationLabel.text = @"No location"; definitely gets called and at that point, entry.location is null.

Any pointers would be great!

Steve.

Code execution never reaches didUpdateLocations and certainly doesn't get inside the completionHandler^ within that.

Very strange!

Its iOS8, not your code. Instead of me trying to act smart by copying and pasting, here is a link with full instructions. Hope it helps. (http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/)

2 Answers

ehud shahak
ehud shahak
3,101 Points

This is the reason for your problem: In iOS 8, this code doesn’t just fail, it fails silently. You will get no error or warning, you won’t ever get a location update and you won’t understand why. Your app will never even ask for permission to use location

the solution: In iOS 8 you need to do two extra things to get location working: Add a key to your Info.plist and request authorization from the location manager asking it to start. There are two Info.plist keys for the new location authorization. One or both of these keys is required. If neither of the keys are there, you can call startUpdatingLocation but the location manager won’t actually start. It won’t send a failure message to the delegate either (since it never started, it can’t fail). It will also fail if you add one or both of the keys but forget to explicitly request authorization.

So the first thing you need to do is to add one or both of the following keys to your Info.plist file:

NSLocationWhenInUseUsageDescription NSLocationAlwaysUsageDescription Both of these keys take a string which is a description of why you need location services. You can enter a string like “Location is required to find out where you are” which, as in iOS 7, can be localized in the InfoPlist.strings file.

Next you need to request authorization for the corresponding location method, WhenInUse or Background. Use one of these calls:

[self.locationManager requestWhenInUseAuthorization]
[self.locationManager requestAlwaysAuthorization]

Here’s a full implementation of a view controller with a location manager asking for WhenInUse (foreground) authorization. This is a basic example which doesn’t take into account whether the user has already denied or restricted location.

#import "ViewController.h"
@import CoreLocation;

@interface ViewController () <CLLocationManagerDelegate>
@property (strong, nonatomic) CLLocationManager *locationManager;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // ** Don't forget to add NSLocationWhenInUseUsageDescription in MyApp-Info.plist and give it a string

    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;
    // Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7.
    if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
        [self.locationManager requestWhenInUseAuthorization];
    }
    [self.locationManager startUpdatingLocation];
}

// Location Manager Delegate Methods    
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    NSLog(@"%@", [locations lastObject]);
}

@end

Genius!

Dee Greene
Dee Greene
8,508 Points

great! this needs to be added to the teachers notes and video! Gabe Nadel

i got an error when put this code

if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
    [self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];

is that wrong with my code ? or i misplace this code

NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
&
[self.locationManager requestWhenInUseAuthorization]
[self.locationManager requestAlwaysAuthorization]

where tu put this code exactly ?

thx for helping

Eric M
Eric M
2,242 Points

Same same. never calls the delegate. Please add notes to the video so folks don't have to dig into answers for this!

In iOS 8, this code doesn’t just fail, it fails silently. You will get no error or warning, you won’t ever get a location update and you won’t understand why. Your app will never even ask for permission to use location. I’m experienced with Core Location and it took me 30 minutes to figure out the new behavior. Baby devs are going to be even more frustrated by this change.

http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/