2012-04-17 82 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

你应该做的是通过检查你的位置管理器获得的第一个更新的时间戳排出第一次更新的第一件事情,它通常缓存最后一个已知的位置。其次要记住准确性,你得到的初始值总是在很宽的范围内。