eri*_*ell 12 performance gps core-location cllocationmanager ios
我有一个应用程序,围绕设备的GPS和来自它的信息.重要的是,位置数据必须准确并且是最新的.我知道该设备受到GPS和GPS限制的限制,但我想知道我是否可以采取任何措施来调整/改善iPhone GPS的性能,特别是在速度区域.由于位置更新滞后于设备实时位置约3-5秒,因此位置管理器报告的速度也远远落后于实时值.就我而言,这太长了.我知道可能没有什么我可以做的,但有没有人在提高iPhone GPS的响应能力方面有任何成功?每一点都有所作为.
编辑1:
正如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];
Run Code Online (Sandbox Code Playgroud)
在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
}
Run Code Online (Sandbox Code Playgroud)
数据处理发生在里面locationManager:didUpdateToLocation:fromLocation:.我不认为这里的低效率是导致滞后的原因.
locationManager:didUpdateToLocation:fromLocation: 调用此方法来更新UI:
- (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];
}
Run Code Online (Sandbox Code Playgroud)
有了几个NSDates和NSLog,我发现整个locationManager:didUpdateToLocation:fromLocation:(不仅仅是标签更新方法)的执行在我的iPhone 4上永远不会超过8毫秒; 换句话说,数据处理不是问题.
fis*_*ear 27
好的,有几件事可以改善你的滞后.首先,始终使用kCLLocationAccuracyBestForNavigation.它与kCLLocationAccuracyBest之间没有真正的电池使用差异,它们都以最高速度使用GPS.主要区别在于Apple的后处理.
其次,没有必要过滤速度== 0.苹果已经进行了过滤:如果你的GPS速度低于某个阈值(约4公里/小时),操作系统会假设你站着不动,它会替代所有后续样本的相同位置值.这样做直到它认为你再次移动.我假设他们这样做是为了避免当你站着不动时在地图上"抖动".实际上,对于一系列"静止"值的最后一个实际值,速度已经降至0,因此如果您对速度== 0进行过滤而不是丢失一个真实的GPS样本.
不幸的是,他们无法避免过滤并获得真实的GPS样本.我和Apple谈过这件事,他们的反应是他们不会改变这种行为.kCLLocationAccuracyBestForNavigation比kCLLocationAccuracyBest执行更少侵略性的过滤,因此最好使用它.
第三,你可能已经这样做了,但要确保你在"didUpdateFromLocation:"的视图上调用"setNeedsDisplay",以确保实际重绘了地图.
如果你做了所有这些,你应该有大约1秒的滞后.如果你想在1秒内改进,你可以尝试使用预测技术.从最后两个位置和给定的速度,您可以计算下一个位置可能的位置,并且已经显示该位置.我的结果好坏参半.它适用于快速移动,不会像驾驶汽车那样突然改变速度.对于像步行或骑自行车这样的慢速运动,它的效果较差.
在iPhone中,我们可以通过两种方法配置位置服务 -
Standard Location Services,即卫星GPS,为您提供更准确的数据.Significant Location Changes它使用A-GPS或通过wi-fi获得位置,这提供了不太准确的数据.我们可以通过这两种方法中的任何一种来配置位置服务,但这取决于应用程序的要求.如果应用程序是a navigation app或a location tracking app然后我们应该使用Standard Location Services但在使用标准服务之前我们要记住,如果您想要更准确的数据,那么您必须忍受battery consume more quickly.如果应用程序不需要更频繁地更新位置更新,accuracy doesn't matter那么我们应该这样做,Significant Location Changes因为它将save a lot of battery与标准位置服务进行比较.
标准位置服务使用desiredAccuracy和distanceFilter值来确定是否以及何时提供事件.
desiredAccuracy是您可以定义GPS硬件所需精度的参数.它使用一些预定义的常量 -
kCLLocationAccuracyBestForNavigation
kCLLocationAccuracyBest
kCLLocationAccuracyNearestTenMeters
kCLLocationAccuracyHundredMeters
kCLLocationAccuracyKilometer
kCLLocationAccuracyThreeKilometers
Run Code Online (Sandbox Code Playgroud)
distanceFilter 是您必须定义距离的参数,表示您要求GPS硬件发送位置更新的距离差距.
在你的情况下,你正在处理速度参数,所以我猜它的东西与导航有关.所以你应该使用Standard Location Services.我认为你也是这样做的,但你所面临的问题是位置更新之间的滞后.在这里,我建议您修改desiredAccuracy和distanceFilter价值这一点-
[locationManager setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters]; [locationManager setDistanceFilter:10.0f];
通过设置值,如果您正在驾驶,您将在不到1秒内获得位置更新.
还有一件事你需要记住,当你获得位置更新时,你应该检查它的timestamp值以忽略旧的位置更新.这是因为当你开始locationManager呼叫时startUpdatingLocation,你得到的第一个位置可能是你的旧位置.此外,您还必须检查horizontalAccuracy价值,因为您获得的前几个位置更新始终不准确,并且可能具有1000或更多的准确性,而您不需要.因此,您必须检查其值以忽略不准确的位置更新.
Note: If you try with different accuracy and different distance filter value then you will be more clear about it how accurate data iPhone GPS hardware return.
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10353 次 |
| 最近记录: |