9

我正在尝试使用 distanceFromLocation: 方法来计算我手里拿着 iPhone 行走的总距离。到目前为止,我一直在四处寻找以帮助纠正我令人困惑、不准确和看似武断的结果。在这些代码片段中,theLabel 只是我的应用程序界面中存在的标签对象,distanceMoved 是我试图存储我走过的总距离的变量,而 locMan 是在我的@interface 文件中声明的位置管理器.

- (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];
}

对于解决我在这里做错的任何帮助将不胜感激。谢谢!

4

4 回答 4

14
  1. 过滤掉缓存的(旧的)位置数据,
  2. 过滤掉无效的定位结果(准确率 < 0),
  3. 将精度要求设置为kCLLocationAccuracyBest,
  4. 设置最小距离过滤器,最好至少 10 米以过滤掉位置噪声。
  5. 编辑oldLocation:当nil时不要计算距离。

您可以做的还有更多,但只要您获得足够好的水平精度(<30m),这应该可以工作。您可以过滤掉低准确度的结果,但是您必须自己跟踪 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];
}

如果您想使用didUpdateLocations执行相同的操作,请针对 iOS6进行编辑:(因为现在不推荐使用上述方法)最简单的解决方案是简单地将每个位置保存在一个属性中,以便在下次更新时您拥有以前的位置。在类中声明一个属性来保存oldLocation

@property (nonatomic, retain) CLLocation* oldLocation;

然后在委托方法中保存每个newLocationoldLocation供下次调用委托方法时使用:

-(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
}
于 2012-04-17T20:00:28.837 回答
0

您没有设置位置管理器的准确性。浏览苹果文档,它类似于accuracy = bestfornavigation。或者其他的东西。这应该会像地狱一样耗尽电池,但就是为了这种目的。

编辑:只记得我手头有它。

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

// Configure the Location Manager
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
于 2012-04-17T03:55:21.620 回答
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];

希望对你有帮助..

于 2012-04-17T03:55:43.357 回答
0

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

于 2012-04-17T04:21:58.757 回答