CLLocationManager 响应能力 [英] CLLocationManager responsiveness

查看:25
本文介绍了CLLocationManager 响应能力的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序,它围绕设备的 GPS 和来自它的信息.位置数据准确和最新是很重要的.我知道该设备受到其 GPS 和 GPS 限制的限制,但我想知道是否可以做任何事情来调整/提高 iPhone GPS 的性能,尤其是在速度方面.由于位置更新比设备的实时位置滞后约 3-5 秒,因此位置管理器报告的速度也远远落后于实时值.就我而言,这太长了.我知道我可能无能为力,但是有没有人在提高 iPhone GPS 的响应能力方面取得了任何成功?每一点都会有所不同.

I have an app that revolves around the device's GPS and the information that comes from it. It is important that the location data be accurate and up-to-date. I know that the device is limited by its GPS and the GPS's limits, but I was wondering if there is anything I can do to tweak/improve the performance of the iPhone GPS, particularly in the speed area. Because location updates lag about 3-5 seconds behind the real-time location of the device, the velocity reported by the location manager also lags that far behind the real-time value. In my case, that is simply too long. I understand that there might not be anything I can do, but has anyone had any success in improving the responsiveness of the iPhone GPS? Every little bit makes a difference.

编辑 1:

按照 Apple 的建议,我的位置管理器位于单例类中.

My location manager is inside a singleton class, as Apple recommends.

SingletonDataController.m 内部:

Inside 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 内部(实际使用位置管理器的地方):

Inside MapView.m (where the location manager is actually used):

- (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: 内部.我不认为这里的低效率是滞后的原因.

The data handling happens inside locationManager:didUpdateToLocation:fromLocation:. I don't believe that inefficiency here is the cause of the lag.

locationManager:didUpdateToLocation:fromLocation: 调用此方法更新 UI:

locationManager:didUpdateToLocation:fromLocation: calls this method to update the 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];
}

通过几个 NSDates 和 NSLogs,我发现在我的 iPhone 4 上执行整个 locationManager:didUpdateToLocation:fromLocation:(不仅仅是标签更新方法)不会超过 8 毫秒;换句话说,数据处理不是问题.

With a couple of NSDates and NSLogs I have found that the execution of the entire locationManager:didUpdateToLocation:fromLocation: (not just the label updating method) never takes more than about 8ms on my iPhone 4; in other words, the data handling isn't the problem.

推荐答案

好的,有几件事可以改善你的延迟.首先,始终使用 kCLLocationAccuracyBestForNavigation.这和 kCLLocationAccuracyBest 之间没有真正的电池使用差异,它们都以最高速度使用 GPS.主要区别在于Apple所做的后处理.

OK, a couple of things could improve your lag. First of all, use kCLLocationAccuracyBestForNavigation always. There is no real battery usage difference between that and kCLLocationAccuracyBest, they both use the GPS at top speed. The main difference is in the post-processing that Apple does.

其次,无需过滤速度 == 0.Apple 已经进行了过滤:如果您从 GPS 获得的速度下降到某个阈值(约 4 公里/小时)以下,操作系统会假定您静止不动,它为所有后续样本替换相同的位置值.它会这样做,直到它认为你再次移动.我认为他们这样做是为了避免在您静止不动时在地图上抖动".事实上,对于一系列静止"值的最后一个实际值,速度已经下降到 0,因此如果您根据速度 == 0 进行过滤,那么您将丢失一个真正的 GPS 样本.

Second, there is no need to filter for speed == 0. Apple already does that filtering: if your speed from the GPS drops below a certain threshold (about 4 km/h), the OS assumes you are standing still, and it substitutes the same location value for all subsequent samples. It does that until it thinks you are moving again. I assume they do that to avoid "jittering" on the map when you are standing still. In fact, speed drops to 0 already for the last real value of a sequence of "standing-still" values, so if you filter on speed == 0 than you are missing one real GPS sample.

不幸的是,他们无法避免过滤并获得真正的 GPS 样本.我和苹果谈过这件事,他们的回答是他们不会改变这种行为.kCLLocationAccuracyBestForNavigation 的过滤不如 kCLLocationAccuracyBest 激进,因此最好使用它.

Unfortunately, they is no way to avoid that filtering and get real GPS samples. I talked to Apple about it, and their response was that they are not going to change the behaviour. kCLLocationAccuracyBestForNavigation does less aggressive filtering than kCLLocationAccuracyBest, so it's best to use that.

第三,您可能已经在执行此操作,但请确保您从didUpdateFromLocation:"开始在您的视图上调用setNeedsDisplay",以确保地图实际上已重新绘制.

Third, you probably are already doing this, but make sure that you call "setNeedsDisplay" on your view right from the "didUpdateFromLocation:", to make sure that the map is actually redrawn.

如果你做了所有这些,你应该有大约 1 秒的延迟.如果您想在 1 秒内有所改进,则可以尝试使用预测技术.根据最后两个位置和给定的速度,您可以计算下一个位置可能在哪里,并且已经显示该位置.我的结果好坏参半.它适用于不会突然改变速度的快速运动,例如驾驶汽车.对于步行或骑自行车等较慢的运动,它的效果较差.

If you do all that, you should have a lag of about 1 second. If you want to improve on the 1 second than you can try to use predictive techniques. From the last two locations, and the given speed, you can calculate where the next location is likely to be, and already display that location. I have had mixed results with that. It works well for fast movement that does not change speed suddenly, like driving a car. It works less well for slower movement like walking or biking.

这篇关于CLLocationManager 响应能力的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆