У меня есть приложение, которое вращается вокруг устройства GPS и информации, поступающей от него. Важно, чтобы данные о местоположении были точными и актуальными. Я знаю, что устройство ограничено GPS и GPS-ограничениями, но мне было интересно, есть ли что-нибудь, что я могу сделать, чтобы настроить/улучшить производительность iPhone GPS, особенно в области скорости. Поскольку обновления местоположения отстают примерно на 3-5 секунд от местоположения устройства в режиме реального времени, скорость, сообщаемая менеджером местоположений, также значительно отстает от значения реального времени. В моем случае это слишком долго. Я понимаю, что не может быть ничего, что я могу сделать, но кто-нибудь имел успех в улучшении чувствительности iPhone GPS? Каждый бит имеет значение.
Изменить 1:
Мой менеджер местоположений находится в классе singleton, как рекомендует Apple.
Внутри SingletonDataController.m:
static CLLocationManager* locationManager;
locationManager = [CLLocationManager new];
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.headingFilter = kCLHeadingFilterNone;
if(([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateCharging) || ([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateFull)) {
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
} else {
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
}
[sharedSingleton setLocationManager:locationManager];
[locationManager release];
Внутри MapView.m(где фактически используется менеджер местоположений):
- (id)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle*)nibBundleOrNil {
//setup
[SingletonDataController sharedSingleton].locationManager.delegate = self;
//more setup
}
- (void)batteryChanged {
if(([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateCharging) || ([[UIDevice currentDevice] batteryState] == UIDeviceBatteryStateFull)) {
[SingletonDataController sharedSingleton].locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
} else {
[SingletonDataController sharedSingleton].locationManager.desiredAccuracy = kCLLocationAccuracyBest;
}
}
- (void)viewDidLoad {
//setup
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(batteryChanged)
name:UIDeviceBatteryStateDidChangeNotification
object:nil];
//other setup
}
Обработка данных происходит внутри locationManager:didUpdateToLocation:fromLocation:
. Я не считаю, что неэффективность здесь является причиной отставания.
locationManager:didUpdateToLocation:fromLocation:
вызывает этот метод для обновления пользовательского интерфейса:
- (void)setLabels:(CLLocation*)newLocation fromOldLocation:(CLLocation*)oldLocation {
//set speed label
if(iterations > 0) {
if(currentSpeed > keyStopSpeedFilter) {
if(isFollowing) {
[mapViewGlobal setRegion:MKCoordinateRegionMake([newLocation coordinate], mapViewGlobal.region.span)];
}
NSString* currentSpeedString;
if(isCustomary) {
currentSpeedString = [[NSString alloc] initWithFormat:@"%.1f miles per hour", (currentSpeed * 2.23693629f)];
} else {
currentSpeedString = [[NSString alloc] initWithFormat:@"%.1f km per hour", (currentSpeed * 3.6f)];
}
[speedLabel setText:currentSpeedString];
[currentSpeedString release];
} else {
speedLabel.text = @"Not moving";
}
}
//set average speed label
if(iterations > 4 && movementIterations > 2) {
NSString* averageSpeedString;
if(isCustomary) {
averageSpeedString = [[NSString alloc] initWithFormat:@"%.1f miles per hour", (float)((speedAverages / (long double)movementIterations) * 2.23693629f)];
} else {
averageSpeedString = [[NSString alloc] initWithFormat:@"%.1f km per hour", (float)((speedAverages / (long double)movementIterations) * 3.6f)];
}
[averageSpeedLabel setText:averageSpeedString];
[averageSpeedString release];
}
//set elapsed time label
NSInteger seconds = [[NSDate date] timeIntervalSinceDate:dataObject.locationManagerStartDate];
NSInteger minutes = seconds / 60;
NSInteger hours = minutes / 60;
//get remainder
seconds %= 60;
NSString* timeString;
NSString* secondsString;
NSString* minutesString;
NSString* hoursString;
if((seconds % 60) < 10) {
secondsString = [[NSString alloc] initWithFormat:@"0%i", seconds];
} else {
secondsString = [[NSString alloc] initWithFormat:@"%i", seconds];
}
if((minutes % 60) < 10) {
minutesString = [[NSString alloc] initWithFormat:@"0%i", minutes];
} else {
minutesString = [[NSString alloc] initWithFormat:@"%i", minutes];
}
if((hours % 60) < 10) {
hoursString = [[NSString alloc] initWithFormat:@"0%i", hours];
} else {
hoursString = [[NSString alloc] initWithFormat:@"%i", hours];
}
timeString = [[NSString alloc] initWithFormat:@"%@:%@:%@", hoursString, minutesString, secondsString];
[elapsedTimeLabel setText:timeString];
[timeString release], timeString = nil;
[secondsString release], secondsString = nil;
[minutesString release], minutesString = nil;
[hoursString release], hoursString = nil;
NSString* totalDistanceString;
if(isCustomary) {
totalDistanceString = [[NSString alloc] initWithFormat:@"Total: %.2f mi", (float)distance * 0.000621371192f];
} else {
totalDistanceString = [[NSString alloc] initWithFormat:@"Total: %.2f km", (float)distance / 1000.0f];
}
[customTopBar setTitle:totalDistanceString];
[totalDistanceString release];
}
С несколькими NSDates и NSLogs я обнаружил, что выполнение всего locationManager:didUpdateToLocation:fromLocation:
(а не только метода обновления меток) никогда не занимает более 8 мс на моем iPhone 4; другими словами, обработка данных не является проблемой.