diff --git a/UULocation.h b/UULocation.h index da9b58c..de1f4c6 100644 --- a/UULocation.h +++ b/UULocation.h @@ -43,10 +43,13 @@ //Global settings interface. + (BOOL) isAuthorizedToTrack; + (BOOL) isTrackingDenied; + + (BOOL) canRequestTracking; // Returns NO if status is anything but kCLAuthorizationStatusNotDetermined, which will result in nothing happening when tracking is requested + (void) requestStartTracking:(void(^)(BOOL authorized))callback; + + (void) requestStartWhenInUseTracking:(void (^)(BOOL))callback; + + (void) startTracking; // You should call this in your requestStartTracking handler (or when isAuthorizedToTrack) to turn on full location monitoring (heavy battery use) + (void) requestStopTracking; - + (void) startTrackingSignificantLocationChanges; + + (void) startTrackingSignificantLocationChanges; // You should call this in your requestStartTracking handler (or when isAuthorizedToTrack) to turn on sporadic location monitoring (light battery use) + (void) stopTrackingSignficantLocationChanges; + (CLLocationDistance) distanceThreshold; diff --git a/UULocation.m b/UULocation.m index 8749fc9..a1d6f86 100644 --- a/UULocation.m +++ b/UULocation.m @@ -110,22 +110,40 @@ + (BOOL) isTrackingDenied return [CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied; } ++ (BOOL) canRequestTracking +{ + return [CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined; +} + + (BOOL) isAuthorizedToTrack { - return ([CLLocationManager locationServicesEnabled] && ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways)); + return ([CLLocationManager locationServicesEnabled] && ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse)); } + (void) requestStartTracking:(void(^)(BOOL authorized))callback +{ + [self requestTrackingWithSelector:@selector(requestAlwaysAuthorization) callback:callback]; +} + ++ (void)requestStartWhenInUseTracking:(void (^)(BOOL))callback +{ + [self requestTrackingWithSelector:@selector(requestWhenInUseAuthorization) callback:callback]; +} + ++ (void)requestTrackingWithSelector:(SEL)selector callback:(void (^)(BOOL))callback { [UUSystemLocation sharedLocation].authorizationCallback = callback; CLLocationManager* locationManager = [UUSystemLocation sharedLocation].clLocationManager; - if ([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) + if ([locationManager respondsToSelector:selector]) { NSString* usageDescription = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]; NSAssert(usageDescription != nil, @"You must set a description in your plist for NSLocationAlwaysUsageDescription"); - [locationManager performSelector:@selector(requestAlwaysAuthorization)]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [locationManager performSelector:selector]; +#pragma clang diagnostic pop } else { @@ -133,6 +151,11 @@ + (void) requestStartTracking:(void(^)(BOOL authorized))callback } } ++ (void) startTracking +{ + [[UUSystemLocation sharedLocation] startTracking]; +} + + (void) requestStopTracking { [[UUSystemLocation sharedLocation] stopTracking]; @@ -244,11 +267,14 @@ - (id) init - (void) startTracking { - [self.clLocationManager startUpdatingLocation]; - - if (self.clLocationManager.location) + if ([UULocationMonitoringConfiguration isAuthorizedToTrack]) { - [self checkForNewLocation:self.clLocationManager.location]; + [self.clLocationManager startUpdatingLocation]; + + if (self.clLocationManager.location) + { + [self checkForNewLocation:self.clLocationManager.location]; + } } } @@ -259,7 +285,10 @@ - (void) stopTracking - (void) startTrackingSignificantLocationChanges { - [self.clLocationManager startMonitoringSignificantLocationChanges]; + if ([UULocationMonitoringConfiguration isAuthorizedToTrack]) + { + [self.clLocationManager startMonitoringSignificantLocationChanges]; + } } - (void) stopTrackingSignificantLocationChanges @@ -318,10 +347,9 @@ - (void) checkForNewLocation:(CLLocation*)reportedLocation - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { - if (self.authorizationCallback && (status != kCLAuthorizationStatusNotDetermined)) - { - [self startTracking]; - self.authorizationCallback(status == kCLAuthorizationStatusAuthorizedAlways); + if (self.authorizationCallback != nil) { + self.authorizationCallback(status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse); + self.authorizationCallback = nil; } } @@ -330,7 +358,7 @@ - (BOOL) shouldUseLocationUpdate:(CLLocation*)reportedLocation if (!self.lastReportedLocation || //!CLLocationCoordinate2DIsValid(self.clLocation.coordinate) || [self.lastReportedLocation.clLocation distanceFromLocation:reportedLocation] > self.distanceThreshold || - [self.lastReportedLocation.clLocation.timestamp timeIntervalSinceDate:reportedLocation.timestamp] > self.timeThreshold || + [self.lastReportedLocation.clLocation.timestamp timeIntervalSinceDate:reportedLocation.timestamp] * -1.0 > self.timeThreshold || reportedLocation.horizontalAccuracy < self.lastReportedLocation.clLocation.horizontalAccuracy) { return YES; @@ -339,6 +367,12 @@ - (BOOL) shouldUseLocationUpdate:(CLLocation*)reportedLocation return NO; } +- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations +{ + [self checkForNewLocation:[locations lastObject]]; +} + +// For iOS 6 - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)reportedLocation fromLocation:(CLLocation *)oldLocation; { [self checkForNewLocation:reportedLocation]; diff --git a/UUProgressView.m b/UUProgressView.m index 0bace96..0055295 100644 --- a/UUProgressView.m +++ b/UUProgressView.m @@ -29,6 +29,7 @@ @interface UUProgressView () +@property (nonatomic, retain) UIView* scrimView; @property (nonatomic, retain) UIView* backgroundView; @property (nonatomic, retain) UILabel* label; @property (nonatomic, retain) UIActivityIndicatorView* spinner; @@ -59,7 +60,7 @@ + (UUProgressView*) globalProgressView if (theProgressView == nil) { theProgressView = [[UUProgressView alloc] initWithMessage:@"Loading..."]; - + UIView* parent = [[UIApplication sharedApplication] keyWindow]; theProgressView.center = parent.center; [parent addSubview:theProgressView]; @@ -78,6 +79,7 @@ - (id) initWithMessage:(NSString*)message if (self != nil) { + [self createScrimView]; [self createBackgroundView]; [self createSpinnerView]; [self createLabelView]; @@ -103,6 +105,14 @@ - (void) dealloc #endif } +- (void) createScrimView +{ + UIView* parent = [[UIApplication sharedApplication] keyWindow]; + self.scrimView = UU_AUTORELEASE([[UIView alloc] initWithFrame:parent.frame]); + self.backgroundView.backgroundColor = [UIColor clearColor]; + [parent addSubview:self.scrimView]; +} + - (void) createBackgroundView { self.backgroundView = UU_AUTORELEASE([[UIView alloc] initWithFrame:self.frame]); @@ -147,12 +157,26 @@ - (void) updateMessage:(NSString*)message - (void) show:(BOOL)animated { - [self showProgressViewWithBounceAnimation]; + if (animated) { + [self showProgressViewWithBounceAnimation]; + } + else { + [self.layer removeAllAnimations]; + self.transform = CGAffineTransformIdentity; + self.hidden = NO; + self.scrimView.hidden = NO; + } } - (void) hide:(BOOL)animated { - [self hideProgressViewWithBounceAnimation]; + if (animated) { + [self hideProgressViewWithBounceAnimation]; + } + else { + self.hidden = YES; + self.scrimView.hidden = YES; + } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -163,6 +187,7 @@ - (void) showProgressViewWithBounceAnimation { self.transform = CGAffineTransformMakeScale(0.001, 0.001); self.hidden = NO; + self.scrimView.hidden = NO; [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^ { @@ -195,6 +220,7 @@ - (void) hideProgressViewWithBounceAnimation completion:^(BOOL finished) { self.hidden = YES; + self.scrimView.hidden = YES; }]; }