Reputation: 85
I need to know if I am near to a saved Geo-location
in my app within a range starting at 10 Meters
to 500 Meters
in background. I have used startMonitoringForSignificantLocationChange
but I am not getting accurate results. Instead using startupdatinglocation
is giving results as accurate as 7 meters
. I am planning to add a NSTimer
to call startupdatinglocation
every 1 minute
.
Is there any other solutions?
Upvotes: 0
Views: 3087
Reputation: 2668
First of all, please don't call startUpdatingLocation every minute. You will kill your users battery life on their devices. Location services utilizes a large amount of battery power to operate. Also, once you call startUpdatingLocation
, it will run until you call stopUpdatingLocation
.
There are properties you can set on CLLocationManager
to configure it to your needs. Like...
@property(assign, nonatomic) CLLocationDistance distanceFilter
@property(assign, nonatomic) CLLocationAccuracy desiredAccuracy
distanceFilter
description: The minimum distance (measured in meters) a device must move horizontally before an update event is generated.
desiredAccuracy
can be one of the following:
kCLLocationAccuracyBestForNavigation
kCLLocationAccuracyBest;
kCLLocationAccuracyNearestTenMeters;
kCLLocationAccuracyHundredMeters;
kCLLocationAccuracyKilometer;
kCLLocationAccuracyThreeKilometers;
Depending on the configuration of your CLLocationManager
object, the device will use certain geo location hardware versus others. Sometimes simply using cell tower triangulation will be sufficient and is the quickest way to get a semi accurate location. Other times it might need to utilize GPS, which will drain battery life very quickly and takes much longer to achieve a location but is in most cases much more accurate.
I would recommend starting an NSTimer, but utilize it for the opposite of what you had planned. Utilize it to stopUpdatingLocation
after a reasonable amount of time if CLLocationManager
isn't able to get an accurate enough location. You DO NOT want to leave location services running for ever. Having this timer set to something like 30 seconds will ensure that it is shut down after the timeout.
Also, you will need to implement the CLLocationManagerDelegate method:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
In this method you will need to check the timestamp
of the location to ensure it is recent. You will also need to check the horizontalAccuracy
of the location to ensure it is within the desired accuracy range. Here is an example of how to do this...
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
// Ensure we get a recent and accurate location
NSDate * locationTimestamp = [newLocation timestamp];
NSTimeInterval timeDifference = [locationTimestamp timeIntervalSinceNow];
double thirtyMins = (30 * 60 * -1);
BOOL locationTimestampIsCurrent = (timeDifference > thirtyMins);
BOOL isAccurateLocation = (newLocation.horizontalAccuracy <= 3000.00);
if (locationTimestampIsCurrent && isAccurateLocation) {
NSLog(@"Shutting down location services, we have a good locaton.");
[self stopListeningForLocation];
} else {
// Do nothing, let this method be called again with a new "newLocation" to check its validity.
}
}
From iOS 6 the above method is deprecated, instead use the following delegate method:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
To get the newest location simply fetch the last object of the locations array like so:
CLLocation *location = [locations lastObject];
Upvotes: 2
Reputation: 4214
You are really starting from scratch with those questions. I suggest you follow Rob and Abhijit links. You also may benefit from experimenting with my code on Github:
Upvotes: 0