diff --git a/Libraries/Geolocation/Geolocation.js b/Libraries/Geolocation/Geolocation.js index 4f49ba9bf..251666f4b 100644 --- a/Libraries/Geolocation/Geolocation.js +++ b/Libraries/Geolocation/Geolocation.js @@ -27,10 +27,11 @@ var subscriptions = []; var updatesEnabled = false; type GeoOptions = { - timeout: number, - maximumAge: number, - enableHighAccuracy: bool, + timeout?: number, + maximumAge?: number, + enableHighAccuracy?: bool, distanceFilter: number, + useSignificantChanges?: bool, } /** @@ -124,7 +125,7 @@ var Geolocation = { /* * Invokes the success callback whenever the location changes. Supported - * options: timeout (ms), maximumAge (ms), enableHighAccuracy (bool), distanceFilter(m) + * options: timeout (ms), maximumAge (ms), enableHighAccuracy (bool), distanceFilter(m), useSignificantChanges (bool) */ watchPosition: function(success: Function, error?: Function, options?: GeoOptions): number { if (!updatesEnabled) { diff --git a/Libraries/Geolocation/RCTLocationObserver.m b/Libraries/Geolocation/RCTLocationObserver.m index d442ad754..f30a7b9dd 100644 --- a/Libraries/Geolocation/RCTLocationObserver.m +++ b/Libraries/Geolocation/RCTLocationObserver.m @@ -32,6 +32,7 @@ typedef struct { double maximumAge; double accuracy; double distanceFilter; + BOOL useSignificantChanges; } RCTLocationOptions; @implementation RCTConvert (RCTLocationOptions) @@ -47,7 +48,8 @@ typedef struct { .timeout = [RCTConvert NSTimeInterval:options[@"timeout"]] ?: INFINITY, .maximumAge = [RCTConvert NSTimeInterval:options[@"maximumAge"]] ?: INFINITY, .accuracy = [RCTConvert BOOL:options[@"enableHighAccuracy"]] ? kCLLocationAccuracyBest : RCT_DEFAULT_LOCATION_ACCURACY, - .distanceFilter = distanceFilter + .distanceFilter = distanceFilter, + .useSignificantChanges = [RCTConvert BOOL:options[@"useSignificantChanges"]] ?: NO, }; } @@ -108,6 +110,7 @@ static NSDictionary *RCTPositionError(RCTPositionErrorCode code, NSDictionary *_lastLocationEvent; NSMutableArray *_pendingRequests; BOOL _observingLocation; + BOOL _usingSignificantChanges; RCTLocationOptions _observerOptions; } @@ -117,7 +120,10 @@ RCT_EXPORT_MODULE() - (void)dealloc { - [_locationManager stopUpdatingLocation]; + _usingSignificantChanges ? + [_locationManager stopMonitoringSignificantLocationChanges] : + [_locationManager stopUpdatingLocation]; + _locationManager.delegate = nil; } @@ -133,14 +139,18 @@ RCT_EXPORT_MODULE() #pragma mark - Private API -- (void)beginLocationUpdatesWithDesiredAccuracy:(CLLocationAccuracy)desiredAccuracy distanceFilter:(CLLocationDistance)distanceFilter +- (void)beginLocationUpdatesWithDesiredAccuracy:(CLLocationAccuracy)desiredAccuracy distanceFilter:(CLLocationDistance)distanceFilter useSignificantChanges:(BOOL)useSignificantChanges { [self requestAuthorization]; _locationManager.distanceFilter = distanceFilter; _locationManager.desiredAccuracy = desiredAccuracy; + _usingSignificantChanges = useSignificantChanges; + // Start observing location - [_locationManager startUpdatingLocation]; + _usingSignificantChanges ? + [_locationManager startMonitoringSignificantLocationChanges] : + [_locationManager startUpdatingLocation]; } #pragma mark - Timeout handler @@ -154,7 +164,9 @@ RCT_EXPORT_MODULE() // Stop updating if no pending requests if (_pendingRequests.count == 0 && !_observingLocation) { - [_locationManager stopUpdatingLocation]; + _usingSignificantChanges ? + [_locationManager stopMonitoringSignificantLocationChanges] : + [_locationManager stopUpdatingLocation]; } } @@ -195,7 +207,9 @@ RCT_EXPORT_METHOD(startObserving:(RCTLocationOptions)options) _observerOptions.accuracy = MIN(_observerOptions.accuracy, request.options.accuracy); } - [self beginLocationUpdatesWithDesiredAccuracy:_observerOptions.accuracy distanceFilter:_observerOptions.distanceFilter]; + [self beginLocationUpdatesWithDesiredAccuracy:_observerOptions.accuracy + distanceFilter:_observerOptions.distanceFilter + useSignificantChanges:_observerOptions.useSignificantChanges]; _observingLocation = YES; } @@ -206,7 +220,9 @@ RCT_EXPORT_METHOD(stopObserving) // Stop updating if no pending requests if (_pendingRequests.count == 0) { - [_locationManager stopUpdatingLocation]; + _usingSignificantChanges ? + [_locationManager stopMonitoringSignificantLocationChanges] : + [_locationManager stopUpdatingLocation]; } } @@ -269,7 +285,9 @@ RCT_EXPORT_METHOD(getCurrentPosition:(RCTLocationOptions)options if (_locationManager) { accuracy = MIN(_locationManager.desiredAccuracy, accuracy); } - [self beginLocationUpdatesWithDesiredAccuracy:accuracy distanceFilter:options.distanceFilter]; + [self beginLocationUpdatesWithDesiredAccuracy:accuracy + distanceFilter:options.distanceFilter + useSignificantChanges:options.useSignificantChanges]; } #pragma mark - CLLocationManagerDelegate @@ -306,7 +324,9 @@ RCT_EXPORT_METHOD(getCurrentPosition:(RCTLocationOptions)options // Stop updating if not observing if (!_observingLocation) { - [_locationManager stopUpdatingLocation]; + _usingSignificantChanges ? + [_locationManager stopMonitoringSignificantLocationChanges] : + [_locationManager stopUpdatingLocation]; } // Reset location accuracy if desiredAccuracy is changed. @@ -356,8 +376,9 @@ static void checkLocationConfig() { #if RCT_DEV if (!([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"] || - [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"])) { - RCTLogError(@"Either NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription key must be present in Info.plist to use geolocation."); + [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"] || + [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysAndWhenInUseUsageDescription"])) { + RCTLogError(@"Either NSLocationWhenInUseUsageDescription or NSLocationAlwaysUsageDescription or NSLocationAlwaysAndWhenInUseUsageDescription key must be present in Info.plist to use geolocation."); } #endif }