Skip to content

Instantly share code, notes, and snippets.

@advantis
Last active December 27, 2015 13:19
Show Gist options
  • Save advantis/7332481 to your computer and use it in GitHub Desktop.
Save advantis/7332481 to your computer and use it in GitHub Desktop.
Simple location detector
//
// Copyright © 2013 Yuri Kotov
//
#import <CoreLocation/CoreLocation.h>
typedef void(^ADVLocationHandler)(CLLocation *location, NSError *error);
@interface ADVLocationDetector : NSObject
@property (nonatomic) NSTimeInterval timeoutInterval;
@property (nonatomic) CLLocationDistance desiredAccuracy;
@property (readonly, nonatomic) CLLocation *location;
@property (strong, nonatomic) ADVLocationHandler handler;
- (void) detect;
- (void) stop;
@end
//
// Copyright © 2013 Yuri Kotov
//
#import "ADVLocationDetector.h"
static const NSTimeInterval LocationMaxAge = 5.0;
static const NSTimeInterval TimeoutInterval = 2.0;
static const CLLocationDistance HorizontalAccuracy = 15.0;
@interface ADVLocationDetector () <CLLocationManagerDelegate>
@property (strong, nonatomic) CLLocation *location;
@property (strong, nonatomic) CLLocationManager *manager;
@end
@implementation ADVLocationDetector
- (id) init
{
if ((self = [super init]))
{
_manager = [CLLocationManager new];
_manager.desiredAccuracy = kCLLocationAccuracyBest;
_manager.delegate = self;
self.timeoutInterval = TimeoutInterval;
self.desiredAccuracy = HorizontalAccuracy;
}
return self;
}
- (void)dealloc {
_manager.delegate = nil;
}
- (void) setDesiredAccuracy:(CLLocationDistance)accuracy
{
_desiredAccuracy = accuracy;
self.manager.distanceFilter = accuracy;
}
- (void) consumeLocation:(CLLocation *)location
{
[self.manager stopUpdatingLocation];
if (self.handler) self.handler(location, nil);
}
- (void) consumeError:(NSError *)error
{
[self.manager stopUpdatingLocation];
if (self.handler) self.handler(nil, error);
}
- (void) detect
{
[self.manager startUpdatingLocation];
}
- (void) stop
{
[self.manager stopUpdatingLocation];
self.location = nil;
}
#pragma mark - CLLocationManagerDelegate
- (void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *location = [locations lastObject];
NSTimeInterval age = -[location.timestamp timeIntervalSinceNow];
if (LocationMaxAge < age) return; // Outdated location
if (location.horizontalAccuracy < 0) return; // Invalid location
if (!self.location || location.horizontalAccuracy < self.location.horizontalAccuracy)
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
self.location = location;
if (location.horizontalAccuracy < self.desiredAccuracy)
{
[self consumeLocation:location];
}
else
{
[self performSelector:@selector(consumeLocation:)
withObject:location
afterDelay:self.timeoutInterval];
}
}
}
- (void) locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
if (error.code == kCLErrorLocationUnknown)
{
[self performSelector:@selector(consumeError:)
withObject:error
afterDelay:TimeoutInterval];
}
else
{
[self consumeError:error];
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment