Skip to content

Instantly share code, notes, and snippets.

@hyperspacemark
Last active February 16, 2016 10:47
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save hyperspacemark/654240e27c3f547a8fbc to your computer and use it in GitHub Desktop.
Save hyperspacemark/654240e27c3f547a8fbc to your computer and use it in GitHub Desktop.
@interface TRLocationController : NSObject
- (RACSignal *)requestWhenInUseAuthorization;
- (RACSignal *)updateCurrentLocation;
@end
@import CoreLocation;
#import "TRLocationController.h"
#import "TRWeatherLocation.h"
#import "CLLocation+TRRecentLocation.h"
@interface TRLocationController () <CLLocationManagerDelegate>
@property (nonatomic) CLLocationManager *locationManager;
@end
@implementation TRLocationController
#pragma mark - Initializers
- (instancetype)init
{
self = [super init];
if (!self) return nil;
self.locationManager = [CLLocationManager new];
self.locationManager.delegate = self;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
return self;
}
#pragma mark - Properties
- (RACSignal *)requestWhenInUseAuthorization
{
if ([self needsAuthorization]) {
[self.locationManager requestWhenInUseAuthorization];
return [self didAuthorize];
} else {
return [self authorized];
}
}
- (RACSignal *)updateCurrentLocation
{
RACSignal *currentLocationUpdated = [[[self didUpdateLocations] map:^id(NSArray *locations) {
return locations.lastObject;
}] filter:^BOOL(CLLocation *location) {
return !location.isStale;
}];
RACSignal *locationUpdateFailed = [[[self didFailWithError] map:^id(NSError *error) {
return [RACSignal error:error];
}] switchToLatest];
return [[[[RACSignal merge:@[currentLocationUpdated, locationUpdateFailed]] take:1] initially:^{
[self.locationManager startUpdatingLocation];
}] finally:^{
[self.locationManager stopUpdatingLocation];
}];
}
#pragma mark - Private
- (BOOL)needsAuthorization
{
return ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined);
}
- (RACSignal *)didAuthorize
{
return [[[[self didChangeAuthorizationStatus] ignore:@(kCLAuthorizationStatusNotDetermined)] map:^id(NSNumber *status) {
return @(status.integerValue == kCLAuthorizationStatusAuthorizedWhenInUse);
}] take:1];
}
- (RACSignal *)authorized
{
BOOL authorized = ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse);
return [RACSignal return:@(authorized)];
}
#pragma mark - CLLocationManagerDelegate Signals
- (RACSignal *)didUpdateLocations
{
return [[self rac_signalForSelector:@selector(locationManager:didUpdateLocations:) fromProtocol:@protocol(CLLocationManagerDelegate)] reduceEach:^id(CLLocationManager *manager, NSArray *locations) {
return locations;
}];
}
- (RACSignal *)didFailWithError
{
return [[self rac_signalForSelector:@selector(locationManager:didFailWithError:) fromProtocol:@protocol(CLLocationManagerDelegate)] reduceEach:^id(CLLocationManager *manager, NSError *error) {
return error;
}];
}
- (RACSignal *)didChangeAuthorizationStatus
{
return [[self rac_signalForSelector:@selector(locationManager:didChangeAuthorizationStatus:) fromProtocol:@protocol(CLLocationManagerDelegate)] reduceEach:^id(CLLocationManager *manager, NSNumber *status) {
return status;
}];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment