2012-04-17 37 views
9

我想使用distanceFromLocation:方法來計算我手中的iPhone與我一起行走的總距離。到目前爲止,我一直在尋找幫助彌補我混亂,不準確,看似任意的結果。在這些代碼片段中,標籤只是存在於我的應用界面中的一個標籤對象,distanceMoved是我試圖存儲我走過的總距離的變量,而locMan是在我的@interface文件中聲明的位置管理器。CLLocation方法的距離distanceFromLocation:不準確的結果

- (void)viewDidLoad 
{ 
    locMan = [[CLLocationManager alloc] init]; 
    locMan.delegate = self; 
    [locMan startUpdatingLocation]; 
    isInitial = true; 
    distanceMoved = 0.0; 
    [super viewDidLoad]; 
} 

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation 
{ 
    distanceMoved += [newLocation distanceFromLocation: oldLocation]; 
    theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved]; 
} 

任何幫助解決我在做什麼錯在這裏將不勝感激。謝謝!

回答

13
  1. 篩選出緩存(舊)的位置數據,
  2. 篩選出無效的位置結果(精度< 0),
  3. 集精度要求設置爲kCLLocationAccuracyBest
  4. 設置的最小距離過濾器,優選在至少10米以過濾位置噪音。
  5. 編輯:當oldLocation爲零時,不計算距離。

還有更多你可以做,但這應該工作,只要你得到足夠好的horizo​​nalAccuracy(< 30米)。您可以過濾掉低精度的結果,但是您必須自己跟蹤一下這個更復雜一點的oldLocation。

添加NSLog(見下文),以便了解發生了什麼。如果你仍然沒有得到好的結果發佈的NSLog的輸出,所以我們可以看到發生了什麼,並幫助更多。

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation 
{ 
    NSTimeInterval age = -[newLocation.timestamp timeIntervalSinceNow]; 

    if (age > 120) return; // ignore old (cached) updates 

    if (newLocation.horizontalAccuracy < 0) return; // ignore invalid udpates 

    // EDIT: need a valid oldLocation to be able to compute distance 
    if (oldLocation == nil || oldLocation.horizontalAccuracy < 0) return; 

    CLLocationDistance distance = [newLocation distanceFromLocation: oldLocation]; 

    NSLog(@"%6.6f/%6.6f to %6.6f/%6.6f for %2.0fm, accuracy +/-%2.0fm", 
     oldLocation.coordinate.latitude, 
     oldLocation.coordinate.longitude, 
     newLocation.coordinate.latitude, 
     newLocation.coordinate.longitude, 
     distance, 
     newLocation.horizontalAccuracy); 

    distanceMoved += distance; 
    theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved]; 
} 

- (void)viewDidLoad 
{ 
    locMan = [[CLLocationManager alloc] init]; 
    locMan.delegate = self; 
    locMan.desiredAccuracy = kCLLocationAccuracyBest; 
    locMan.distanceFilter = 10; 

    [locMan startUpdatingLocation]; 
    isInitial = true; 
    distanceMoved = 0.0; 
    [super viewDidLoad]; 
} 

編輯iOS6的,如果你想要做的使用didUpdateLocations:(因爲上面的方法現在已經過時)最簡單的辦法是簡單地在屬性保存每個位置,這樣你有下一次更新相同以前的位置。聲明一個屬性的類來保存oldLocation

@property (nonatomic, retain) CLLocation* oldLocation; 

然後在委託方法您將每個newLocation用作oldLocation下一次委託方法被稱爲:

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocations:(NSArray *)locations 
{ 
    CLLocation* newLocation = [locations lastObject]; 

    NSTimeInterval age = -[newLocation.timestamp timeIntervalSinceNow]; 

    if (age > 120) return; // ignore old (cached) updates 

    if (newLocation.horizontalAccuracy < 0) return; // ignore invalid udpates 

    // EDIT: need a valid oldLocation to be able to compute distance 
    if (self.oldLocation == nil || self.oldLocation.horizontalAccuracy < 0) { 
     self.oldLocation = newLocation; 
     return; 
    } 

    CLLocationDistance distance = [newLocation distanceFromLocation: self.oldLocation]; 

    NSLog(@"%6.6f/%6.6f to %6.6f/%6.6f for %2.0fm, accuracy +/-%2.0fm", 
     self.oldLocation.coordinate.latitude, 
     self.oldLocation.coordinate.longitude, 
     newLocation.coordinate.latitude, 
     newLocation.coordinate.longitude, 
     distance, 
     newLocation.horizontalAccuracy); 

    distanceMoved += distance; 
    theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved]; 

    self.oldLocation = newLocation; // save newLocation for next time 
} 
+0

我剛剛使用了這個確切的代碼,但我將距離過濾器更改爲1.出於某種原因,我的距離從-1開始。這裏是我的輸出行走後大約2米前進: 2012-04-17 17:58:05.341 LocationManagerTest2 [422:707] 0.000000/0.000000至39.856110/-74.940113 -1m,精度+/- 10m 2012-04 -17 17:58:10.248 LocationManagerTest2 [422:707] 39.856110/-74.940113到39.856165/-74.940107爲6米,準確度+/- 50m 2012-04-17 17:58:11.248 LocationManagerTest2 [422:707] 39.856165/- 74.940107到39.856223/-74.940010爲10米,準確度爲+/- 50m 距離移動到了15米左右 - 太多了 – bnasty 2012-04-17 22:00:37

+0

我之前也試過使用這段代碼,並且我得到了一些看似準確的結果,遠離 – bnasty 2012-04-17 22:05:10

+0

-1距離是您oldLocation爲0的位置,這可能意味着oldLocation參數爲零。您還需要添加一個支票(請參閱上面的編輯)。報告水平時準確度不高,準確度爲50m!這意味着GPS沒有足夠好的信號,這意味着報告的位置可以向任何方向偏離50米。 – progrmr 2012-04-18 01:31:12

0

您沒有設置您的位置管理器的準確性。瀏覽蘋果文檔,它就像精確度= bestfornavigation。或者其他的東西。這應該消耗電池像地獄,但意味着這種目的。

編輯:只記得我手頭上有它。

// Create the Location Manager 
locationManager = [[CLLocationManager alloc] init]; 

// Configure the Location Manager 
locationManager.delegate = self; 
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation; 
+0

我試着爲所需的精度設置所有不同的常量,但仍然沒有運氣。現在,我的應用將以距離移動-1.00000開始,而不是0.000000。問題可能在於我的核心位置框架或我的iPhone本身嗎? – bnasty 2012-04-17 04:15:29

+0

NSlog舊的和新的位置,看他們是如何變化的。然後告訴我,我可以對發生了什麼有一個想法。 ive與位置經理很好地工作,我記得如果你不正確地配置它,它確實是奇怪的東西 – Pochi 2012-04-17 04:38:10

+0

經緯度座標似乎是正確的,因爲每次位置更新時,從上一次的新位置正在存儲爲舊位置。出於某種原因,兩個地點之間的距離正在計算爲極高的數字。 – bnasty 2012-04-17 11:40:45

0
CLLocationDistance distance = [secondLocation distanceFromLocation:firstLocation]; // distance is expressed in meters 

CLLocationDistance kilometers = distance/1000.0; 
// or you can also use this.. 
CLLocationDistance meters = distance; 

NSString *distanceString = [[NSString alloc] initWithFormat: @"%f", kilometers]; 

flot totaldistancecovered = [distanceString floatValue]; 

//Now,you can use this float value for addition... 
// distanceMoved should be float type variable which is declare in .h file... 

distanceMoved = distanceMoved + totaldistancecovered ; 
theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved]; 

希望這將幫助你..

+0

'CLLocationDistance'只是'double'的一個typedef,所以沒有理由將它轉換爲一個字符串,然後再回來做數學運算。 – pr1001 2013-08-21 14:17:00

0

你應該做的是通過檢查你的位置管理器獲得的第一個更新的時間戳排出第一次更新的第一件事情,它通常緩存最後一個已知的位置。其次要記住準確性,你得到的初始值總是在很寬的範圍內。