问题
I am working on an iOS app that's focuses on pedestrians in a block of buildings (campus). I have developed a good enough (I believe) user's location update but, I would like anyone more expert than me to give me some tips, advices on accurate location, battery's issues etc. In addition, is it possible to stop the location update and start it again after n seconds? Is a thought that I did in order to save energy. As it is at the moment, app is detecting current location, but, blue dot (user) is still moving around and I don't like that. There is something that can be done?
Below is my didUpdateToLocation method:
App is reading buildings' info from a file (stored on device)
- (void)viewDidLoad{
[super viewDidLoad];
if ([self checkForInternet]) {
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.distanceFilter = 10.0f;
_locationManager.desiredAccuracy = 20.0f;
[_locationManager startUpdatingLocation];
}
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
if (newLocation.horizontalAccuracy > manager.desiredAccuracy) return;
[self.mapView removeAnnotations:listOfAnn];
[listOfAnn removeAllObjects];
if ([manager locationServicesEnabled]) {
for (NSString* row in rows){
NSArray* cells = [row componentsSeparatedByString:@"\t"];
CLLocationCoordinate2D newCoord;
newCoord.latitude = [[cells objectAtIndex:5]floatValue];
newCoord.longitude = [[cells objectAtIndex:6]floatValue];
CLLocation *locB = [[CLLocation alloc] initWithLatitude:newLocation.coordinate.latitude longitude:newLocation.coordinate.longitude];
CLLocation *centerLoc = [[CLLocation alloc] initWithLatitude:CAMPUS_LATITUDE longitude:CAMPUS_LONGITUDE];
CLLocationDistance borders = [locB distanceFromLocation:centerLoc];
if ((int)round(borders) > 500) {
BuildingViewController *newBuilding = [[BuildingViewController alloc] initBuildingWithName:[cells objectAtIndex:2] coordinates:newCoord shortDescription:[cells objectAtIndex:4] image:(NSString*)[cells objectAtIndex:3] inDistance: borders];
if ([[prefs stringForKey:newBuilding.title] isEqualToString:[prefs stringForKey:@"userName"]]) {
[newBuilding retrieveID];
[listOfAnn addObject:newBuilding];
}
} else{
CLLocation *locA = [[CLLocation alloc] initWithLatitude:newCoord.latitude longitude:newCoord.longitude];
CLLocationDistance distance = [locA distanceFromLocation:locB];
BuildingViewController *newBuilding = [[BuildingViewController alloc] initBuildingWithName:[cells objectAtIndex:2]
coordinates:newCoord shortDescription:[cells objectAtIndex:4] image:(NSString*)[cells objectAtIndex:3]
inDistance: distance];
if ((int)round(distance) < 100 ||
[[prefs stringForKey:newBuilding.title] isEqualToString:[prefs stringForKey:@"userName"]]){
[newBuilding retrieveID];
[listOfAnn addObject:newBuilding];
}
}
}
[self.mapView addAnnotations:listOfAnn];
}
}
回答1:
Γεια σου Παναγιώτη.
You should read the official documentation about location services
It is an excellent guide and should get cover everything. I will do a quick recap for you and explain you the pros and cons for each available method, as I have worked extensively with Core Location services for our App:
There are 3 different ways to get the users location in iOS.
- Normal GPS location monitorins (pros: very acurate and updates quickly, cons: drains the battery way too fast)
- Significant Location services (pros: very battery efficient, can start the app from background, even when terminated if a region is entered, without requiring a background location monitoring task and permission, cons: very inaccurate in both determining the location and receiveing updates of location changes)
- Region Monitoring (pros: very battery efficient, can start the app from background, even when terminated if a region is entered, without requiring a background location monitoring task and permission cons: inaccurate in getting notifications about the regions entered, max 20 regions can be monitored by app)
So depending on the accuracy you want, you have to select the service. Of course, if you are going the GPS way, like you use in your code, you should always turn off the location updating after you get an update and request the position again, only after a certain period of time, else your app will drain the user's battery.
And of course you can restart the user's location updates at anytime. If you require location updates in many view controllers in your app, I suggest you create a singleton class for the location manager!
As for GPS monitoring, in your CoreLocation delegate method, didUpdateToLocation, do the following:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSDate* eventDate = newLocation.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
//prevent Location caching... (only accepts cached data 1 minute old)
if( abs(howRecent) < 60.0) {
[self.locationManager stopUpdatingLocation];
//capture the location... (this is your code)
//update location after 90 seconds again
[self performSelector:@selector(startUpdatingLocation) withObject:nil afterDelay:90];
}
}
and to update the location again:
- (void)startUpdatingLocation {
if([CLLocationManager authorizationStatus]==kCLAuthorizationStatusAuthorized || [CLLocationManager authorizationStatus]==kCLAuthorizationStatusNotDetermined) {
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
}
and to be sure we have canceled our performSelector in case the user changes viewController, add this to:
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[NSObject cancelPreviousPerformRequestsWithTarget:self];
}
来源:https://stackoverflow.com/questions/13847229/users-location-and-batterys-consumption