DrKey
DrKey

Reputation: 3495

Check if an instance of CLLocationManager isUpdatingLocation

I need to know if an instance of CLLocationManager (in this case called gps) is updating location calling the proper method

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation

In my case the complete method is:

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
    //NSLog(@"didUpdateToLocation: %@", newLocation);
    currentLocation = newLocation;

    if (currentLocation != nil) {
        longitude.text = [NSString stringWithFormat:@"%.3f", currentLocation.coordinate.longitude];
        latitude.text = [NSString stringWithFormat:@"%.3f", currentLocation.coordinate.latitude];
    }

    address.text = NULL;
    [activityIndicator setHidden:NO];
    [activityIndicator startAnimating];
    NSLog(@"Resolving the Address");
    [geocoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placemarks, NSError *error) {
        //NSLog(@"Found placemarks: %@, error: %@", placemarks, error);
        if (error == nil && [placemarks count] > 0) {
            placemark = [placemarks lastObject];
            [address sizeToFit];
            address.text = [NSString stringWithFormat:@"%@, %@\n%@ %@\n%@",
                            [self sanitizedDescription:placemark.thoroughfare],
                            [self sanitizedDescription:placemark.subThoroughfare],
                            [self sanitizedDescription:placemark.postalCode],
                            [self sanitizedDescription:placemark.locality],
                            [self sanitizedDescription:placemark.country]];


            if (address.text != NULL)
            {
                gpsTimer = [NSTimer scheduledTimerWithTimeInterval:10
                                                            target:gps
                                                          selector:@selector(startUpdatingLocation)
                                                          userInfo:nil
                                                           repeats:NO];
                [address sizeToFit];
                [gps stopUpdatingLocation];
            }
        } else {
            NSLog(@"%@", error.debugDescription);
        }
    } ];

}

How can I do?

Thanks in advance :)

Upvotes: 4

Views: 5721

Answers (4)

MD Aslam Ansari
MD Aslam Ansari

Reputation: 1565

Below is a simple example code to show how to deal with this issue.

import Foundation
import CoreLocation

public class LocationManager : NSObject, CLLocationManagerDelegate{  

    var locationManager: CLLocationManager?
    public var isLocationUpdate: Bool = false


     override public init() {
        super.init()

        self.locationManager = CLLocationManager()
        self.locationManager!.delegate = self

        if #available(iOS 9.0, *) {            
            self.locationManager!.requestWhenInUseAuthorization()          
        }
        self.locationManager!.startUpdatingLocation()
        self.isLocationUpdate = false
    }


public func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
   self.isLocationUpdate = true
  print(locations)

}


public func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {

        //Retrieving the error code.
      if let code = (error as NSError).code{
        isLocationUpdate = false
      }
}

Upvotes: 2

Mathias
Mathias

Reputation: 3981

There really is no way for you to check "is my delegate 'active' for this locationmanager?".

What you need to do is keep track yourself of whether you're done with the location updates.

I'm not sure if this is what you need, but here's what i do:

1- when i start requesting updates, i do as you do, i.e. through requestlocationupdates and a delegate.

2- In the case where i don't get the updates i need, i want to time out after some time, so that my app doesn't wait for a location forever, in this case i use a Selector with a timeout:

[self performSelector:@selector(fetchLocationTimeout) withObject:nil afterDelay:LOCATION_LISTEN_TIME];

and in the selector:

(void)fetchLocationTimeout{
    if(!finished){
        [self stopUpdatingLocation];    
        [delegate locationFinished:bestEffortAtLocation];//see more on this below
    }
}

3- in my didupdate-delegate i both store away the "best" location i have gotten, and if i decide that the new location is "good enough", i finish my location-fetching process:

(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{

    if(newLocation is the best i have){

        self.bestEffortAtLocation = newLocation;

    }
// test the measurement to see if it is more accurate than the previous measurement

    if (bestEffortAtLocation == nil || newLocation is the best i have) {
// store the location as the "best effort"
        if (bestEffortAtLocation is good enough and i want to use it) {        
            [self stopUpdatingLocation];            
        // we can also cancel our previous performSelector:withObject:afterDelay: - it's no longer necessary
        SEL selector = NSSelectorFromString(@"fetchLocationTimeout");
            [NSObject cancelPreviousPerformRequestsWithTarget:self selector:selector object:nil];
            [delegate locationFinished:bestEffortAtLocation];
        }
    }
}

Finally, this is my method which is called above, both from within the didupdate-delegate and from the selector timeout to reduce the risk of a race condition:

(void)stopUpdatingLocation{
    finished = true;
    NSLog(@"stopUpdatingLocation! manager: %@", [locationManager description]);
    [locationManager stopUpdatingLocation];
    locationManager.delegate = nil;
}

Final note: the "delegate" i'm calling when i'm done is my own interface describing a class that knows how to take care of the result of a location-fetching process. it has only one method to be implemented "locationFinished", as you can see.

Hope this helps even though my code-pasting skills aren't exactly ninja.

Upvotes: 0

Pini Cheyni
Pini Cheyni

Reputation: 5437

Apple deprecated one of the primary location manager delegate methods in iOS 6, so if you are supporting older versions of iOS as well as the current version, you will need to include support for both delegate methods:

iOS 2 - iOS 5:

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation

iOS 6 and later:

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations

Upvotes: 0

Nicolas Manzini
Nicolas Manzini

Reputation: 8546

subclass your CLLocationManager and add a BOOL that is set to yes when your delegate method gets called...

You can also simply tell your location manager to stop within the delegate method

Upvotes: 8

Related Questions