CLLocation方法遇到问题distanceFromLocation:结果不准确

bna*_*sty 9 iphone objective-c core-location cllocation

我正在尝试使用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];
}
Run Code Online (Sandbox Code Playgroud)

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

pro*_*rmr 14

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

你可以做的更多但是如果你获得足够好的水平准确度(<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];
}
Run Code Online (Sandbox Code Playgroud)

编辑iOS6如果你想使用didUpdateLocations做同样的事情:(因为上面的方法现已弃用),最简单的解决方案是简单地将每个位置保存在属性中,以便在下次更新时获得之前的位置.在类中声明一个属性来保存oldLocation:

@property (nonatomic, retain) CLLocation* oldLocation;
Run Code Online (Sandbox Code Playgroud)

然后在委托方法中保存每个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
}
Run Code Online (Sandbox Code Playgroud)