Reputation: 3495
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
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
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
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
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