CLLocation returning (null) coordinates - ios

Below is code for my CLLocationManagerDelegate. I call the delegate methods using:
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
The delegate methods:
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", 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 didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
//get current location of phone:
if (newLocation != nil) {
_m.longitude = [NSString stringWithFormat:#"%.8f", newLocation.coordinate.longitude];
_m.latitude = [NSString stringWithFormat:#"%.8f", newLocation.coordinate.latitude];
_m.timestamp = newLocation.timestamp;
NSLog(#"didUpdateToLocation: %#", newLocation);
}
CLLocation *currentLocation = newLocation;
}
When I call the didUpdateToLocation method, I've verified through debugging that newLocation is not nil. _m is an object declared in my header, and is not nil either. The same is true for locationManager. However, when I try to set _m.latitude etc. and NSLog them, they all show up as (null). The didUpdateToLocation NSLog results in a line like this:
didUpdateToLocation: <+47.64312748,-122.12163262> +/- 65.00m (speed -1.00 mps / course -1.00) # 7/15/14, 9:26:07 AM Pacific Daylight Time
I'm not sure where I'm going wrong.

Your code looks correct. So probably you get null in logs because _m == nil.

Related

iOS: Get Coordinates on button click, then stop all location services

Right now, I have it so when a button is clicked, it starts location services, sets the latitude/longitude variables. But location still continues to be running in the background.
I want is so when I click a button it finds the latitude/longitude, all location services stop.
Here's what I have currently.
- (IBAction)startButton:(id)sender {
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
NSLog(#"%#", [self lat]);
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", 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 didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
[self setLat:[NSString stringWithFormat:#"%.6f", currentLocation.coordinate.latitude]];
}
}
Another problem is, if I instantly try to retrieve the value of the lat property, it returns null, most likely because it takes a second or two to find the location.
So I would also need to stop any further code to be run until the lat/long properties are set. For example, How would I stop the otherFunction from running until the latitude/longitude are found:
- (IBAction)startButton:(id)sender {
[self updateLocation];
[self otherFunction];
}
- (void)updateLocation
{
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", 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 didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
[self setLat:[NSString stringWithFormat:#"%.6f", currentLocation.coordinate.latitude]];
[locationManager stopUpdatingLocation]
}
}
Any help/ideas would be appreciated!
In your last function, after you verify that the currentLocation is not nil, then you should check for the accuracy of currentLocation, then call your setLat: function, then stop updating the location. See this post for more details:
CLLocationManager and accuracy issues - any experiences?

NSLocation location keep updating

I'm trying to get the current location only once, but didUpdateToLocation is being called over and over. I'm calling getCurrentLocation in viewDidLoad. How can i only let it get the location once?
- (IBAction)getCurrentLocation:(id)sender {
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", 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 didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
for (int i = 0; i < [storesArray count]-1; i++) {
CLLocationDegrees latitude = [[[storesArray objectAtIndex:i] valueForKey:#"lat"] doubleValue];
CLLocationDegrees longitude = [[[storesArray objectAtIndex:i] valueForKey:#"long"] doubleValue];
CLLocation *checkPosition = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
CLLocationDistance distance = [checkPosition distanceFromLocation:currentLocation];
float distanceInKm = distance / 1000;
if (distanceInKm > 5) {
NSLog(#"%#", distanceInKm);
}
}
}
}
You need to call
[locationManager stopUpdatingLocation];
cf. official doc:
Call this method whenever your code no longer needs to receive location-related events. Disabling event delivery gives the receiver the option of disabling the appropriate hardware (and thereby saving power) when no clients need location data. You can always restart the generation of location updates by calling the startUpdatingLocation method again.

How to get 'current location only' in iOS?

I am using Core Location framework to getting location in iOS. I use, CLLocationManager *locationManager; and call [locationManager startUpdatingLocation];
Problem is I only need instantaneous location but startUpdatingLocation keep on giving me location. To stop this I can use [self.locationManager stopUpdatingLocation], but this look like a way out or hack.
Is there any better way to just get current location in iOS?
in your .h file
#import <CoreLocation/CoreLocation.h>
#interface LocationSearchViewController : UIViewController<UITextFieldDelegate,CLLocationManagerDelegate>
{
CLLocationManager *locationManager;
}
in your .m file
- (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", 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 didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"didUpdateToLocation: %#", newLocation);
[locationManager stopUpdatingLocation]; // when u got the lat and long it stop uoatde the location
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
NSString *getcurrlong = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude];
NSSting *getcurrlat = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude];
}
}
You can't think of location in those precise terms. You'll get back increasingly accurate locations from the location manager and it's up to you to decide when it's accurate enough. You have to weigh this against power usage and time. The location updates will never be completely accurate. The will never be returned immediately. The device has to power up hardware, then listen for GPS/WiFi/Cell signals and use all those to calculate location.
There's no way to ask for "my precise current location" and have it given to you immediately. Location is not a property like [NSDate date]. You can only ask for best-estimate location updates and they will only come to you in imprecise measurements, and never instantaneously (excepting cached location).
Check it
-(void)getCurrentLocation
{
locationManager = [[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.delegate = self;
[locationManager startUpdatingLocation];
startLocation = nil;
}
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
if (startLocation == nil)
{
startLocation = newLocation;
[locationManager setDelegate:nil];
locationManager = nil;
}
}

Objective C, iOS 7 - CLLocationManager: didUpdateLocations is being called only once

EDIT: Ok, I just have noticed that the problem is exclusive of iOS 7. I'm still being unable to solve it, however, so I suppouse I'll try with the sugestions bellow. Thanks to all!
¡Hi! I'm programming a navigator app, and I need to update the user position whenever is possible. I have two View Controllers that use CLLocation manager. In both of them I've added this line:
#import <CoreLocation/CoreLocation.h>
And then added the to the interface declaration, and I'm setting this as a property in the .h file, and synthetizing afterwards:
#property (strong, nonatomic) CLLocationManager *locationManager;
After that, I'm launching de locationManager in the viewDidLoad, this way:
if(self){
locationManager = [[CLLocationManager alloc] init];
//locationManager.delegate = self;
[locationManager setDelegate:self];
[locationManager setDistanceFilter:kCLHeadingFilterNone];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBestForNavigation];
[locationManager startUpdatingLocation];
}
And here are my delegate methods.
For the first View:
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", 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 didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"didUpdateToLocation: %#", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
homeLatitude = [[NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude] doubleValue];
homeLongitude = [[NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude] doubleValue];
NSLog(#"Updated! -> hl = %f, hlg = %f", homeLatitude, homeLongitude);
}
}
For the second view. As you can see, I replaced the old didUpdateToLocation with didUpdateLocations, as a desperate try.
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", 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 didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"didUpdateToLocation: %#", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
NSLog(#"Tarzan boy");
_testLabel.text = [NSString stringWithFormat:#"Oh DAMN!!!!"];
}
}*/
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
NSLog(#"didUpdateToLocation: %#", [locations lastObject]);
CLLocation *currentLocation = [locations lastObject];
if (currentLocation != nil) {
currentLatitude = [[NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude] doubleValue];
currentLongitude = [[NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude] doubleValue];
NSLog(#"Updated! (MapWithRoutesViewController) -> hl = %f, hlg = %f", currentLatitude, currentLongitude);
_testLabel.text = [NSString stringWithFormat:#"Update! -> hl = %f, hlg = %f", currentLatitude, currentLongitude];
//Aquí es donde borramos el lugar al que llegaron.
if(mapView){
if(followMe){
CLLocationCoordinate2D *c = &((CLLocationCoordinate2D){.latitude = currentLatitude, .longitude = currentLongitude});
[mapView.mapView as_setCenterCoordinate:*c zoomLevel:32 animated:NO];
_ourStepper.value = [mapView.mapView as_zoomLevel];
}
if([mapView getNearestDestinyDistance:currentLocation] < 150.0){
NSLog(#"Hay que eliminar el primer destino del MapView");
mapView.destinoActual++;
}
if([mapView getNearestPointDistance:currentLocation] > 200.0){
NSLog(#"Hay que recalcular la ruta al destinoActual");
SpinnerView *spinner = [SpinnerView loadSpinnerIntoView:self.view];
spinner.tag = 98;
while (![mapView recalculateRoutesTo:currentLocation]) {
//do nothin...
}
[spinner removeSpinner];
}
}
}
//[locationManager stopUpdatingLocation];
}
As you can see, the line
//[locationManager stopUpdatingLocation];
is commented. Well, the problem is driving me crazy is that the code above works as a charm in the first view controller, and update periodically as I expected. But in the second view, it works only the first time, and never updates again. I programmed these methods in different times, so I can't remember if I did something to the first view I didn't to the second. But they are in the same app, so I assume there's no problem with libraries or permissions. Any help or hint is welcome, thanks!
First off, if you are doing navigation, you should be registering for significant change notifications. Go read the documentation on that here. It's much more efficient. You will have to turn it off when you are not using it, but it's much better. Support for it goes all the way back to iOS 4. That's 99% of the user population for sure.
I had a similar situation in my application and implemented a singleton that handles all location updates and then fires off NSNotificaitons to the foreground threads.
Create a singleton class that handles the location updates View would
register to listen to LOCATION_CHANGE updates perhaps Background
singleton object registers as the delegate for the location manager
This may not be the answer you are looking for but i know it worked in my case.
Found the solution here. The locationManager works when I launch it this way:
if(self){
locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];
[locationManager setDistanceFilter:kCLHeadingFilterNone];
//change the desired accuracy to kCLLocationAccuracyBest
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
//SOLUTION: set setPausesLocationUpdatesAutomatically to NO
[locationManager setPausesLocationUpdatesAutomatically:NO];
[locationManager startUpdatingLocation];
}
I'll work anyway in performance like Rob suggested. Thanks to all for the help!

How to make my ios app appears in Location Services in the settings

I wrote an CLLocationManager ios app. However, I cannot see my app appears in the Location Services in the settings on my iPhone. Do I need to set a specific value in plist in my ios project in Xcode? Thanks in advance!
It should appear automatically once code that actually requires location tracking is being called (whenever the popup first show: do you allow...)
try calling something like this:
[self.locationManager startUpdatingLocation];
And that should do it
In iOS -8 need to do some changes :
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
if([locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]){
[locationManager requestWhenInUseAuthorization];
}else{
[locationManager startUpdatingLocation];
}
need to add 2 extra key in plist with blank value
1)NSLocationWhenInUseUsageDescription
2)NSLocationAlwaysUsageDescription
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", 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 didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"didUpdateToLocation: %#", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
NSString *strLat = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude];
NSString *strLong = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude];
}
}

Resources