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

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!

Related

getting different location even if I am not moving

I am using below code for getting longitude and latitude , but it gives me diifferent values even if I am not moving from my place
locationmanager=[[CLLocationManager alloc]init];
geocoder=[[CLGeocoder alloc]init];
locationmanager.delegate=self;
locationmanager.desiredAccuracy=kCLLocationAccuracyBest;
if([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
[locationmanager requestWhenInUseAuthorization];
}
[locationmanager startUpdatingLocation];
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"error" message:#"Failed to get Location." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
CLLocation *currentlocation=newLocation;
if (currentlocation!=nil)
{
longitude=currentlocation.coordinate.longitude;
latitude=currentlocation.coordinate.latitude;
}
[geocoder reverseGeocodeLocation:currentlocation completionHandler:^(NSArray *placemarks, NSError *error) {
} ];
}
please guide me, I want same location, if I am not moving from my place.
Cellular network location gives an approximate area were the phone existing. It is based on the service providers tower.So current location will automatically changes a bit depending on network/gps location tracking/accuracy.
I recommend you to get location using distance filter, so until you are in that region your current address will remain same as location only updates for every X meters.
locationManager.distanceFilter = 100;//Your own distance
i.e.,
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
_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.
_locationManager.distanceFilter = 100;
// Once configured, the location manager must be "started".
[_locationManager startUpdatingLocation];
Hope this helps.
In ViewController.h file:
#interface ViewController : UIViewController<CLLocationManagerDelegate>
{
CLLocationManager *location;
}
In ViewController.m file:
- (void)viewDidLoad
{
location = [[CLLocationManager alloc] init];
location.delegate = self;
location.distanceFilter = 100;
[location requestWhenInUseAuthorization];
[location requestAlwaysAuthorization];
[location startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *locati = [locations lastObject];
float lat=locati.coordinate.latitude;
float lon=locati.coordinate.longitude;
NSLog(#"%f %f",lat,lon);
[location stopUpdatingLocation];
}
In your info.plist add :

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;
}
}

can't get location on iOS - doesn't call delegate methods

i have a problem with the locationManager under iOS 6.
-(void) getLocationTest {
// Create a location manager instance to determine if location services are enabled. This manager instance will be
// immediately released afterwards.
manager = [[CLLocationManager alloc] init];
if (![manager locationServicesEnabled]) {
UIAlertView *servicesDisabledAlert = [[UIAlertView alloc] initWithTitle:#"Location Services Disabled" message:#"You currently have all location services for this device disabled. If you proceed, you will be asked to confirm whether location services should be reenabled." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[servicesDisabledAlert show];
//[servicesDisabledAlert release];
}
manager.delegate = self;
manager.desiredAccuracy = kCLLocationAccuracyKilometer;
// Set a movement threshold for new events.
manager.distanceFilter = 500;
[manager startUpdatingLocation];
//[manager release];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
double testDe = 2.434;
testDe = testDe * 2;
}
-(void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations {
CLLocation *location = [locations objectAtIndex:0];
double locDouble = location.coordinate.latitude;
NSString* locName = [[NSString alloc] initWithFormat:#"Hello, %f!", locDouble];
//[locations lastObject];
//NSLog(#"lat%f - lon%f", location.coordinate.latitude, location.coordinate.longitude);
}
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
double testD = 2.434;
testD = testD * 2;
}
i have breakpoints in all the delegate methods, but none of them is being called.
Does someone know what i'm doing wrong? or how i can find out where the error is?
i would be grateful for every answer!
thanks!
Are you testing this on a device or in the simulator? In the simulator you have to manually set some location from the simulator app menu. It's in Debug/Location/.

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