2012-01-20 25 views
4

我遇到了一個非常奇怪的情況,我有一個使用CLLocationManager獲取用戶當前位置的應用程序。我正在使用與Apple的CLLocationManager示例代碼非常相似的包裝類。它開始尋找位置,並等待它獲得符合某些標準的位置(時間戳記年齡,準確性)。當我在一個非常全球定位系統的地區時,所有的工作都很好。CLLocationManager可能受其他應用程序影響嗎?

現在的問題。當我在我的辦公室時,在GPS信號看起來很糟糕的WiFi連接上,我打開我的應用程序,它永遠找不到合適的位置。我退出應用程序,打開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]; 
     } 
    } 
} 
+0

我們很多人都想知道同樣的事情..... – KevinDTimm

+0

在緩存方面,或者Foursquare如何收集位置座標? – nickbona

+0

我已經看到了一些有趣的行爲:在啓動時收集不與(例如)谷歌地圖嬉戲的地點。雖然他們(似乎)立即獲取信息,但我的應用程序似乎並未儘快獲取位置更新。在我的應用程序之前運行地圖(例如)提高了我的應用程序的性能:(這看起來不正確 – KevinDTimm

回答

1

你爲什麼要使用

self.locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters 

,而不是kCLLocationAccuracyBest?當然,如果沒有將水平精度與此相比較,就像你自己注意到的那樣,負數常數 - 但是一些合理的其他數值(比如100.0m)代替。你有沒有嘗試過它是否有所作爲?

期望的精度控制了多少努力投入位置採集(對於更高的值,GPS甚至沒有打開,因爲您可以檢查Xcode/Instruments/EnergyDiagnostics)。較少的努力會導致準確性降低和/或獲得職位的時間更多。這聽起來不合理嗎?

根據我自己的觀察:當向iOS詢問具有某種期望精度的位置時,結果可能是任何事情:較不準確(即在具有較差的GPS接收的建築物中),精度要求高或實際上更準確(另一個應用程序或同一應用程序的另一個CLlocationManager對象可能會同時要求硬件提供更高的準確性 - 那麼所有其他應用程序都會繼承更好的值,而無需額外的工作)。

除了上面,可能有所作爲的iOS設備是否您正在訪問互聯網,因爲它是一個輔助 GPS接收器。如果由於某些其他互聯網活動而使設備發生在線,可能會出現一些輔助數據下載的副作用。不過,這最後的想法是純粹的猜測。

還有一件事: 如果我沒有在你的代碼中忽略它,那麼你還沒有定義一個距離過濾器。嘗試類似

self.locationManager.distanceFilter = kCLDistanceFilterNone; 

確保您獲得儘可能多的更新。

+0

您將此標記爲正確的答案,但沒有說明三個建議中的哪一個是重要部分。我可以認爲它是所需的準確性設置? – Ant

0

是的,我認爲CLLocationManager緩存在一定程度上,我嘗試了一些東西,比如運行谷歌地圖的位置,我的位置被發現,然後跑我的應用程序,它立即找到我的位置。還嘗試過,運行導航應用程序,找到我的位置,立即殺死它,運行其他使用位置的應用程序,所有應用程序幾乎可以在瞬間找到該位置的鎖。

相關問題