@@ -6,9 +6,9 @@ Licensed to the Apache Software Foundation (ASF) under one
66 to you under the Apache License, Version 2.0 (the
77 "License"); you may not use this file except in compliance
88 with the License. You may obtain a copy of the License at
9-
9+
1010 http://www.apache.org/licenses/LICENSE-2.0
11-
11+
1212 Unless required by applicable law or agreed to in writing,
1313 software distributed under the License is distributed on an
1414 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -65,7 +65,7 @@ - (void)pluginInitialize
6565- (BOOL )isAuthorized
6666{
6767 BOOL authorizationStatusClassPropertyAvailable = [CLLocationManager respondsToSelector: @selector (authorizationStatus )]; // iOS 4.2+
68-
68+
6969 if (authorizationStatusClassPropertyAvailable) {
7070 NSUInteger authStatus = [CLLocationManager authorizationStatus ];
7171#ifdef __IPHONE_8_0
@@ -75,7 +75,7 @@ - (BOOL)isAuthorized
7575#endif
7676 return (authStatus == kCLAuthorizationStatusAuthorizedAlways ) || (authStatus == kCLAuthorizationStatusNotDetermined );
7777 }
78-
78+
7979 // by default, assume YES (for iOS < 4.2)
8080 return YES ;
8181}
@@ -84,7 +84,7 @@ - (BOOL)isLocationServicesEnabled
8484{
8585 BOOL locationServicesEnabledInstancePropertyAvailable = [self .locationManager respondsToSelector: @selector (locationServicesEnabled )]; // iOS 3.x
8686 BOOL locationServicesEnabledClassPropertyAvailable = [CLLocationManager respondsToSelector: @selector (locationServicesEnabled )]; // iOS 4.x
87-
87+
8888 if (locationServicesEnabledClassPropertyAvailable) { // iOS 4.x
8989 return [CLLocationManager locationServicesEnabled ];
9090 } else {
@@ -112,10 +112,10 @@ - (void)startLocation:(BOOL)enableHighAccuracy
112112 }
113113 // PERMISSIONDENIED is only PositionError that makes sense when authorization denied
114114 [self returnLocationError: PERMISSIONDENIED withMessage: message];
115-
115+
116116 return ;
117117 }
118-
118+
119119#ifdef __IPHONE_8_0
120120 NSUInteger code = [CLLocationManager authorizationStatus ];
121121 if (code == kCLAuthorizationStatusNotDetermined && ([self .locationManager respondsToSelector: @selector (requestAlwaysAuthorization )] || [self .locationManager respondsToSelector: @selector (requestWhenInUseAuthorization )])) { // iOS8+
@@ -130,7 +130,7 @@ - (void)startLocation:(BOOL)enableHighAccuracy
130130 return ;
131131 }
132132#endif
133-
133+
134134 // Tell the location manager to start notifying us of location updates. We
135135 // first stop, and then start the updating to ensure we get at least one
136136 // update, even if our location did not change.
@@ -157,7 +157,7 @@ - (void)_stopLocation
157157 if (![self isLocationServicesEnabled ]) {
158158 return ;
159159 }
160-
160+
161161 [self .locationManager stopUpdatingLocation ];
162162 __locationStarted = NO ;
163163 __highAccuracyEnabled = NO ;
@@ -169,14 +169,16 @@ - (void)locationManager:(CLLocationManager*)manager
169169 fromLocation : (CLLocation*)oldLocation
170170{
171171 CDVLocationData* cData = self.locationData ;
172-
172+
173173 cData.locationInfo = newLocation;
174- if (self.locationData .locationCallbacks .count > 0 ) {
175- for (NSString * callbackId in self.locationData .locationCallbacks ) {
176- [self returnLocationInfo: callbackId andKeepCallback: NO ];
174+ @synchronized (self.locationData .locationCallbacks ) {
175+ if (self.locationData .locationCallbacks .count > 0 ) {
176+ for (NSString * callbackId in self.locationData .locationCallbacks ) {
177+ [self returnLocationInfo: callbackId andKeepCallback: NO ];
178+ }
179+
180+ [self .locationData.locationCallbacks removeAllObjects ];
177181 }
178-
179- [self .locationData.locationCallbacks removeAllObjects ];
180182 }
181183 if (self.locationData .watchCallbacks .count > 0 ) {
182184 for (NSString * timerId in self.locationData .watchCallbacks ) {
@@ -193,7 +195,7 @@ - (void)getLocation:(CDVInvokedUrlCommand*)command
193195 [self .commandDelegate runInBackground: ^{
194196 NSString * callbackId = command.callbackId ;
195197 BOOL enableHighAccuracy = [[command argumentAtIndex: 0 ] boolValue ];
196-
198+
197199 if ([self isLocationServicesEnabled ] == NO ) {
198200 NSMutableDictionary * posError = [NSMutableDictionary dictionaryWithCapacity: 2 ];
199201 [posError setObject: [NSNumber numberWithInt: PERMISSIONDENIED] forKey: @" code" ];
@@ -205,14 +207,18 @@ - (void)getLocation:(CDVInvokedUrlCommand*)command
205207 self.locationData = [[CDVLocationData alloc ] init ];
206208 }
207209 CDVLocationData* lData = self.locationData ;
208- if (!lData.locationCallbacks ) {
209- lData.locationCallbacks = [NSMutableArray arrayWithCapacity: 1 ];
210+ @synchronized (self.locationData .locationCallbacks ) {
211+ if (!lData.locationCallbacks ) {
212+ lData.locationCallbacks = [NSMutableArray arrayWithCapacity: 1 ];
213+ }
210214 }
211-
215+
212216 if (!__locationStarted || (__highAccuracyEnabled != enableHighAccuracy)) {
213217 // add the callbackId into the array so we can call back when get data
214- if (callbackId != nil ) {
215- [lData.locationCallbacks addObject: callbackId];
218+ @synchronized (self.locationData .locationCallbacks ) {
219+ if (callbackId != nil ) {
220+ [lData.locationCallbacks addObject: callbackId];
221+ }
216222 }
217223 // Tell the location manager to start notifying us of heading updates
218224 [self startLocation: enableHighAccuracy];
@@ -228,19 +234,19 @@ - (void)addWatch:(CDVInvokedUrlCommand*)command
228234 NSString * callbackId = command.callbackId ;
229235 NSString * timerId = [command argumentAtIndex: 0 ];
230236 BOOL enableHighAccuracy = [[command argumentAtIndex: 1 ] boolValue ];
231-
237+
232238 if (!self.locationData ) {
233239 self.locationData = [[CDVLocationData alloc ] init ];
234240 }
235241 CDVLocationData* lData = self.locationData ;
236-
242+
237243 if (!lData.watchCallbacks ) {
238244 lData.watchCallbacks = [NSMutableDictionary dictionaryWithCapacity: 1 ];
239245 }
240-
246+
241247 // add the callbackId into the dictionary so we can call back whenever get data
242248 [lData.watchCallbacks setObject: callbackId forKey: timerId];
243-
249+
244250 if ([self isLocationServicesEnabled ] == NO ) {
245251 NSMutableDictionary * posError = [NSMutableDictionary dictionaryWithCapacity: 2 ];
246252 [posError setObject: [NSNumber numberWithInt: PERMISSIONDENIED] forKey: @" code" ];
@@ -258,7 +264,7 @@ - (void)addWatch:(CDVInvokedUrlCommand*)command
258264- (void )clearWatch : (CDVInvokedUrlCommand*)command
259265{
260266 NSString * timerId = [command argumentAtIndex: 0 ];
261-
267+
262268 if (self.locationData && self.locationData .watchCallbacks && [self .locationData.watchCallbacks objectForKey: timerId]) {
263269 [self .locationData.watchCallbacks removeObjectForKey: timerId];
264270 if ([self .locationData.watchCallbacks count ] == 0 ) {
@@ -276,7 +282,7 @@ - (void)returnLocationInfo:(NSString*)callbackId andKeepCallback:(BOOL)keepCallb
276282{
277283 CDVPluginResult* result = nil ;
278284 CDVLocationData* lData = self.locationData ;
279-
285+
280286 if (lData && !lData.locationInfo ) {
281287 // return error
282288 result = [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageToErrorObject: POSITIONUNAVAILABLE];
@@ -292,7 +298,7 @@ - (void)returnLocationInfo:(NSString*)callbackId andKeepCallback:(BOOL)keepCallb
292298 [returnInfo setObject: [NSNumber numberWithDouble: lInfo.altitude] forKey: @" altitude" ];
293299 [returnInfo setObject: [NSNumber numberWithDouble: lInfo.coordinate.latitude] forKey: @" latitude" ];
294300 [returnInfo setObject: [NSNumber numberWithDouble: lInfo.coordinate.longitude] forKey: @" longitude" ];
295-
301+
296302 result = [CDVPluginResult resultWithStatus: CDVCommandStatus_OK messageAsDictionary: returnInfo];
297303 [result setKeepCallbackAsBool: keepCallback];
298304 }
@@ -304,17 +310,20 @@ - (void)returnLocationInfo:(NSString*)callbackId andKeepCallback:(BOOL)keepCallb
304310- (void )returnLocationError : (NSUInteger )errorCode withMessage : (NSString *)message
305311{
306312 NSMutableDictionary * posError = [NSMutableDictionary dictionaryWithCapacity: 2 ];
307-
313+
308314 [posError setObject: [NSNumber numberWithUnsignedInteger: errorCode] forKey: @" code" ];
309315 [posError setObject: message ? message: @" " forKey: @" message" ];
310316 CDVPluginResult* result = [CDVPluginResult resultWithStatus: CDVCommandStatus_ERROR messageAsDictionary: posError];
311-
312- for (NSString * callbackId in self.locationData .locationCallbacks ) {
313- [self .commandDelegate sendPluginResult: result callbackId: callbackId];
317+
318+
319+ @synchronized (self.locationData .locationCallbacks ) {
320+ for (NSString * callbackId in self.locationData .locationCallbacks ) {
321+ [self .commandDelegate sendPluginResult: result callbackId: callbackId];
322+ }
323+
324+ [self .locationData.locationCallbacks removeAllObjects ];
314325 }
315-
316- [self .locationData.locationCallbacks removeAllObjects ];
317-
326+
318327 for (NSString * callbackId in self.locationData .watchCallbacks ) {
319328 [self .commandDelegate sendPluginResult: result callbackId: callbackId];
320329 }
@@ -323,7 +332,7 @@ - (void)returnLocationError:(NSUInteger)errorCode withMessage:(NSString*)message
323332- (void )locationManager : (CLLocationManager*)manager didFailWithError : (NSError *)error
324333{
325334 NSLog (@" locationManager::didFailWithError %@ " , [error localizedFailureReason ]);
326-
335+
327336 CDVLocationData* lData = self.locationData ;
328337 if (lData && __locationStarted) {
329338 // TODO: probably have to once over the various error codes and return one of:
@@ -336,10 +345,10 @@ - (void)locationManager:(CLLocationManager*)manager didFailWithError:(NSError*)e
336345 }
337346 [self returnLocationError: positionError withMessage: [error localizedDescription ]];
338347 }
339-
348+
340349 if (error.code != kCLErrorLocationUnknown ) {
341- [self .locationManager stopUpdatingLocation ];
342- __locationStarted = NO ;
350+ [self .locationManager stopUpdatingLocation ];
351+ __locationStarted = NO ;
343352 }
344353}
345354
0 commit comments