diff --git a/gyp/platform-ios.gypi b/gyp/platform-ios.gypi index 81c73975a..7e91648c4 100644 --- a/gyp/platform-ios.gypi +++ b/gyp/platform-ios.gypi @@ -34,8 +34,6 @@ '../platform/ios/MGLUserLocation.m', '../platform/ios/MGLUserLocationAnnotationView.h', '../platform/ios/MGLUserLocationAnnotationView.m', - '../include/mbgl/ios/MGLMetricsLocationManager.h', - '../platform/ios/MGLMetricsLocationManager.m', '../include/mbgl/ios/MGLTypes.h', '../platform/ios/NSBundle+MGLAdditions.h', '../platform/ios/NSBundle+MGLAdditions.m', diff --git a/include/mbgl/ios/MGLMetricsLocationManager.h b/include/mbgl/ios/MGLMetricsLocationManager.h deleted file mode 100644 index 4161fc4dd..000000000 --- a/include/mbgl/ios/MGLMetricsLocationManager.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface MGLMetricsLocationManager : NSObject -@end diff --git a/platform/ios/MGLMapboxEvents.m b/platform/ios/MGLMapboxEvents.m index 8eefd7c05..74693f5c0 100644 --- a/platform/ios/MGLMapboxEvents.m +++ b/platform/ios/MGLMapboxEvents.m @@ -4,9 +4,9 @@ #import #import #import +#import #import "MGLAccountManager.h" -#import "MGLMetricsLocationManager.h" #import "NSProcessInfo+MGLAdditions.h" #import "NSBundle+MGLAdditions.h" #import "NSException+MGLAdditions.h" @@ -130,7 +130,7 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; // strong references. // -@interface MGLMapboxEvents() +@interface MGLMapboxEvents () // All of the following properties are written to only from // the main thread, but can be read on any thread. @@ -140,13 +140,15 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; @property (atomic) NSString *appName; @property (atomic) NSString *appVersion; @property (atomic) NSString *appBuildNumber; -@property (atomic) MGLMetricsLocationManager *locationManager; @property (atomic) NSUInteger flushAt; @property (atomic) NSDateFormatter *rfc3339DateFormatter; @property (atomic) NSURLSession *session; @property (atomic) NSData *digicertCert; @property (atomic) NSData *geoTrustCert; +// Main thread only +@property (nonatomic) CLLocationManager *locationManager; + // The paused state tracker is only ever accessed from the main thread. // @property (nonatomic, getter=isPaused) BOOL paused; @@ -299,6 +301,18 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; _data = nil; [_session invalidateAndCancel]; _session = nil; + + [self stopUpdatingLocation]; +} + +- (void)stopUpdatingLocation { + [_locationManager stopUpdatingLocation]; + + // -[CLLocationManager stopMonitoringVisits] is only available in iOS 8+. + if ([_locationManager respondsToSelector:@selector(stopMonitoringVisits)]) { + [_locationManager stopMonitoringVisits]; + } + _locationManager = nil; } @@ -316,7 +330,22 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; self.paused = NO; _data = [[MGLMapboxEventsData alloc] init]; _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil]; - _locationManager = [[MGLMetricsLocationManager alloc] init]; + + [self startUpdatingLocation]; +} + +- (void)startUpdatingLocation { + _locationManager = [[CLLocationManager alloc] init]; + _locationManager.desiredAccuracy = kCLLocationAccuracyKilometer; + _locationManager.distanceFilter = 10; + _locationManager.delegate = self; + + [_locationManager startUpdatingLocation]; + + // -[CLLocationManager startMonitoringVisits] is only available in iOS 8+. + if ([_locationManager respondsToSelector:@selector(startMonitoringVisits)]) { + [_locationManager startMonitoringVisits]; + } } // Can be called from any thread. Can be called rapidly from @@ -493,12 +522,6 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; return [NSString stringWithFormat:@"%@/%@/%@ %@", self.appName, self.appVersion, self.appBuildNumber, MGLMapboxEventsUserAgent]; } -// Can be called from any thread. -// -- (NSString *) formatDate:(NSDate *)date { - return [self.rfc3339DateFormatter stringFromDate:date]; -} - // Can be called from any thread. // - (NSString *) deviceOrientation { @@ -678,6 +701,46 @@ NSString *const MGLEventGestureRotateStart = @"Rotation"; return result; } +#pragma mark CLLocationManagerDelegate +- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { + // Iterate through locations to pass all data + for (CLLocation *loc in locations) { + [MGLMapboxEvents pushEvent:MGLEventTypeLocation withAttributes:@{ + MGLEventKeyLatitude: @(loc.coordinate.latitude), + MGLEventKeyLongitude: @(loc.coordinate.longitude), + MGLEventKeySpeed: @(loc.speed), + MGLEventKeyCourse: @(loc.course), + MGLEventKeyAltitude: @(loc.altitude), + MGLEventKeyHorizontalAccuracy: @(loc.horizontalAccuracy), + MGLEventKeyVerticalAccuracy: @(loc.verticalAccuracy) + }]; + } +} + +- (void)locationManager:(CLLocationManager *)manager didVisit:(CLVisit *)visit { + [MGLMapboxEvents pushEvent:MGLEventTypeVisit withAttributes:@{ + MGLEventKeyLatitude: @(visit.coordinate.latitude), + MGLEventKeyLongitude: @(visit.coordinate.longitude), + MGLEventKeyHorizontalAccuracy: @(visit.horizontalAccuracy), + MGLEventKeyArrivalDate: [[NSDate distantPast] isEqualToDate:visit.arrivalDate] ? [NSNull null] : [_rfc3339DateFormatter stringFromDate:visit.arrivalDate], + MGLEventKeyDepartureDate: [[NSDate distantFuture] isEqualToDate:visit.departureDate] ? [NSNull null] : [_rfc3339DateFormatter stringFromDate:visit.departureDate] + }]; +} + +- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { + switch (status) { + case kCLAuthorizationStatusDenied: + [self stopUpdatingLocation]; + break; + case kCLAuthorizationStatusAuthorized: + case kCLAuthorizationStatusAuthorizedWhenInUse: + [self startUpdatingLocation]; + break; + default: + break; + } +} + #pragma mark NSURLSessionDelegate - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^) (NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler { diff --git a/platform/ios/MGLMetricsLocationManager.m b/platform/ios/MGLMetricsLocationManager.m deleted file mode 100644 index ce4990740..000000000 --- a/platform/ios/MGLMetricsLocationManager.m +++ /dev/null @@ -1,106 +0,0 @@ -#import "MGLMapboxEvents.h" -#import "MGLMetricsLocationManager.h" - -#import - -@interface MGLMetricsLocationManager() - -@property (nonatomic) CLLocationManager *locationManager; -@property (atomic) NSDateFormatter *rfc3339DateFormatter; - -@end - -@implementation MGLMetricsLocationManager - -- (instancetype) init { - if (self = [super init]) { - _locationManager = [[CLLocationManager alloc] init]; - _locationManager.desiredAccuracy = kCLLocationAccuracyKilometer; - _locationManager.distanceFilter = 10; - [_locationManager setDelegate:self]; - - _rfc3339DateFormatter = [[NSDateFormatter alloc] init]; - NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; - - [_rfc3339DateFormatter setLocale:enUSPOSIXLocale]; - [_rfc3339DateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"]; - // Clear Any System TimeZone Cache - [NSTimeZone resetSystemTimeZone]; - [_rfc3339DateFormatter setTimeZone:[NSTimeZone systemTimeZone]]; - - [self startUpdatingLocation]; - [self startMonitoringVisits]; - } - return self; -} - -- (void)dealloc { - [self stopUpdatingLocation]; - [self stopMonitoringVisits]; -} - -- (void)startUpdatingLocation { - [self.locationManager startUpdatingLocation]; -} - -- (void)stopUpdatingLocation { - [self.locationManager stopUpdatingLocation]; -} - -- (void)startMonitoringVisits { - // -[CLLocationManager startMonitoringVisits] is only available in iOS 8+. - if ([self.locationManager respondsToSelector:@selector(startMonitoringVisits)]) { - [self.locationManager startMonitoringVisits]; - } -} - -- (void)stopMonitoringVisits { - // -[CLLocationManager stopMonitoringVisits] is only available in iOS 8+. - if ([self.locationManager respondsToSelector:@selector(stopMonitoringVisits)]) { - [self.locationManager stopMonitoringVisits]; - } -} - -#pragma mark CLLocationManagerDelegate -- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { - // Iterate through locations to pass all data - for (CLLocation *loc in locations) { - [MGLMapboxEvents pushEvent:MGLEventTypeLocation withAttributes:@{ - MGLEventKeyLatitude: @(loc.coordinate.latitude), - MGLEventKeyLongitude: @(loc.coordinate.longitude), - MGLEventKeySpeed: @(loc.speed), - MGLEventKeyCourse: @(loc.course), - MGLEventKeyAltitude: @(loc.altitude), - MGLEventKeyHorizontalAccuracy: @(loc.horizontalAccuracy), - MGLEventKeyVerticalAccuracy: @(loc.verticalAccuracy) - }]; - } -} - -- (void)locationManager:(CLLocationManager *)manager didVisit:(CLVisit *)visit { - [MGLMapboxEvents pushEvent:MGLEventTypeVisit withAttributes:@{ - MGLEventKeyLatitude: @(visit.coordinate.latitude), - MGLEventKeyLongitude: @(visit.coordinate.longitude), - MGLEventKeyHorizontalAccuracy: @(visit.horizontalAccuracy), - MGLEventKeyArrivalDate: [[NSDate distantPast] isEqualToDate:visit.arrivalDate] ? [NSNull null] : [_rfc3339DateFormatter stringFromDate:visit.arrivalDate], - MGLEventKeyDepartureDate: [[NSDate distantFuture] isEqualToDate:visit.departureDate] ? [NSNull null] : [_rfc3339DateFormatter stringFromDate:visit.departureDate] - }]; -} - -- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { - switch (status) { - case kCLAuthorizationStatusDenied: - [self stopUpdatingLocation]; - [self stopMonitoringVisits]; - break; - case kCLAuthorizationStatusAuthorized: - case kCLAuthorizationStatusAuthorizedWhenInUse: - [self startUpdatingLocation]; - [self startMonitoringVisits]; - break; - default: - break; - } -} - -@end