CLLocationManager 可能会受到其他应用程序的影响吗?

Posted

技术标签:

【中文标题】CLLocationManager 可能会受到其他应用程序的影响吗?【英文标题】:Possible for CLLocationManager to be affected by other apps? 【发布时间】:2012-01-20 15:35:14 【问题描述】:

我在使用 CLLocationManager 获取用户当前位置的应用程序时遇到了一个非常奇怪的情况。我正在使用与 Apple 的 CLLocationManager 示例代码非常相似的包装类。它开始寻找位置,并一直等待,直到获得满足某些标准(时间戳年龄、准确性)的位置。当我在一个 GPS 可访问的区域时,一切正常。

现在的问题。当我在办公室使用 WiFi 连接时,GPS 信号似乎很糟糕,我打开我的应用程序,它永远找不到合适的位置。我退出我的应用程序,打开 Foursquare,它几乎立即找到了我附近的地方,这让我认为它已经找到了我的位置。我退出 Foursquare,然后重新打开我的应用程序,发现它几乎立即找到了我的位置。

谁能解释一下这里可能发生的事情?如果人们认为这会有所帮助,我可以发布一些代码,但这更多的是关于其他应用程序如何对 CLLocationManager 的功能产生积极或消极影响的一般性问题。理想情况下,我很想知道 Foursquare 究竟做了什么来如此快速地获取位置,以及这可能如何导致我的应用程序也突然开始获取位置。

编辑:根据下面的答案,人们似乎经历过跨应用缓存,这很好。但是,它并没有解释为什么 Foursquare 获得了位置,而我的应用程序仅在使用 Foursquare 后才获得位置。下面是我的 CLLocationManager 代码,希望有人能找到一些确凿证据:

- (void) lazyInit 
    if (!self.locationManager) 
        self.locationManager = [[CLLocationManager alloc] init];
        self.locationManager.delegate = self;
        self.locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
        self.reverseGeocoder = [[WPGeocodingService alloc] initWithDelegate:self];
        self.locationAndPlacemark = NO;
    


- (void) getCurrentLocation 
    [self lazyInit];
    self.recentLocation = nil;
    [self performSelector:@selector(timeoutLocationFetch) withObject:nil afterDelay:kLocationFetchTimeout];
    [self.locationManager startUpdatingLocation];


- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation 
    NSLog(@"LocationService:update: <%f,%f> Accuracy: %f", newLocation.coordinate.latitude, newLocation.coordinate.longitude,
          newLocation.horizontalAccuracy);

    // test the age of the location measurement to determine if the measurement is cached
    // in most cases you will not want to rely on cached measurements
    NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];
    if (locationAge > 5.0) return;

    // test that the horizontal accuracy does not indicate an invalid measurement
    if (newLocation.horizontalAccuracy < 0) return;

    // test the measurement to see if it is more accurate than the previous measurement
    if (self.recentLocation == nil || self.recentLocation.horizontalAccuracy > newLocation.horizontalAccuracy) 
        // store the location as the "best effort"
        self.recentLocation = newLocation;
        // test the measurement to see if it meets the desired accuracy
        //
        // IMPORTANT!!! kCLLocationAccuracyBest should not be used for comparison with location coordinate or altitidue 
        // accuracy because it is a negative value. Instead, compare against some predetermined "real" measure of 
        // acceptable accuracy, or depend on the timeout to stop updating. This sample depends on the timeout.
        //
        if (newLocation.horizontalAccuracy <= self.locationManager.desiredAccuracy) 
            // we have a measurement that meets our requirements, so we can stop updating the location
            // 
            // IMPORTANT!!! Minimize power usage by stopping the location manager as soon as possible.
            //
            [self.locationManager stopUpdatingLocation];
            // we can also cancel our previous performSelector:withObject:afterDelay: - it's no longer necessary
            [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(timeoutLocationFetch) object:nil];

            if ([self.delegate respondsToSelector:@selector(locationService:didReceiveLocation:)]) 
                [self.delegate locationService:self didReceiveLocation:self.recentLocation];
            
        
        


- (void)locationManager:(CLLocationManager *)manager  didFailWithError:(NSError *)error 
    NSLog(@"LocationService:error: %@", [error description]);
    if ([error code] != kCLErrorLocationUnknown) 
        [self.locationManager stopUpdatingLocation];
        if ([self.delegate respondsToSelector:@selector(locationService:didFailWithError:)]) 
            [self.delegate locationService:self didFailWithError:error];
        
    


- (void) timeoutLocationFetch 
    NSLog(@"LocationService:timeout");
    [self.locationManager stopUpdatingLocation];
    if (self.recentLocation && [self.delegate respondsToSelector:@selector(locationService:didReceiveLocation:)]) 
        if ([self.delegate respondsToSelector:@selector(locationService:didReceiveLocation:)]) 
            [self.delegate locationService:self didReceiveLocation:self.recentLocation];
        
     else 
        NSError* error = [NSError errorWithDomain:@"Location Error" code:0 userInfo:
                          [NSDictionary dictionaryWithObject:@"The application could not determine your location." forKey:NSLocalizedDescriptionKey]];
        if ([self.delegate respondsToSelector:@selector(locationService:didFailWithError:)]) 
            [self.delegate locationService:self didFailWithError:error];
        
    

【问题讨论】:

我们很多人都想知道同样的事情..... 在缓存方面,还是在 Foursquare 如何收集位置坐标方面? 我看到了一些有趣的行为:启动时收集的位置与(例如)谷歌地图不符。尽管他们(似乎)立即获得信息,但我的应用程序似乎并没有迅速获得位置更新。在我的应用程序之前运行地图(例如)可以提高我的应用程序的性能:( 这似乎不对。 【参考方案1】:

你为什么要使用

self.locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters

而不是kCLLocationAccuracyBest?当然,如果不将水平精度与此进行比较,正如您自己注意到的那样,negative 常数 - 但一些合理的其他值(比如 100.0m)代替。您是否尝试过它是否有所作为?

所需的精度控制在位置获取上投入多少精力(对于更高的值,甚至没有打开 GPS,您可以使用 Xcode/Instruments/EnergyDiagnostics 进行检查)。更少的努力会导致更少的准确性和/或更多的时间来获得一个位置。这听起来不合理吗?

根据我自己的观察:当向 ios 询问具有某种所需精度的位置时,结果可以是任何东西:不太准确(即在 GPS 接收不佳的建筑物中)、符合要求的准确度,或者实际上比需要(另一个应用程序或同一应用程序的另一个 CLlocationManager 对象可能同时向硬件要求更高的精度 - 然后所有其他应用程序无需额外努力即可继承更好的值)。

除了上述之外,它可能影响您的 iOS 设备是否访问互联网,因为它是一个 辅助 GPS 接收器。如果设备由于其他一些互联网活动而恰好在线,那么下载一些辅助数据可能会产生某种副作用。不过,这最后的想法纯属猜测。

还有一点: 如果我没有在您的代码中忽略它,那么您还没有定义距离过滤器。尝试类似

self.locationManager.distanceFilter = kCLDistanceFilterNone;

以确保您获得尽可能多的更新。

【讨论】:

您将此标记为正确答案,但没有说明三个建议中的哪一个是重要部分。我可以假定它是期望的准确度设置吗?【参考方案2】:

是的,我认为 CLLocationManager 在某种程度上缓存了位置,我尝试了一些东西,比如运行 GoogleMaps,找到了我的位置,然后运行我的应用程序,它立即找到了我的位置。也试过,运行一个导航应用,找到我的位置,立即杀死它,运行其他使用位置的应用程序,所有应用程序几乎可以瞬间找到该位置的锁。

【讨论】:

以上是关于CLLocationManager 可能会受到其他应用程序的影响吗?的主要内容,如果未能解决你的问题,请参考以下文章

CLLocationManager 警报自行解除

我多久可以从 CLLocationManager 获得更新?

带有外部 GPS 的 CLLocationManager/MKMapView

我应该为 CLLocationManager 选择哪种所需的精度?

使用 iOS CLLocationManager 节省电池

停止返回缓存的 CLLocationManager 位置