CoreLocation查找行进距离并将其用作变量iOS

时间:2013-02-25 02:07:28

标签: ios gps core-location distance

我发出的警报只有在手机移动一定距离后才会关闭(强迫用户下床)。我需要能够找到警报响起后行驶的距离,然后采取这个距离,并在一个方法中使用它,如果已经行进了最小距离,则关闭警报声。有任何想法吗? 我使用以下内容更新位置。有关如何将其纳入禁用警报的任何想法吗?

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation     *)newLocation fromLocation:(CLLocation *)oldLocation
{
if(!newLocation) {
    NSLog(@"No movement");
}

if ((oldLocation.coordinate.latitude != newLocation.coordinate.latitude) &&
    (oldLocation.coordinate.longitude != newLocation.coordinate.longitude))
{



    CLLocation *loc1 = [[CLLocation alloc] initWithLatitude:oldLocation.coordinate.latitude longitude:oldLocation.coordinate.longitude];
    CLLocation *loc2 = [[CLLocation alloc] initWithLatitude:newLocation.coordinate.latitude longitude:newLocation.coordinate.longitude];
    CLLocationDistance distance = [loc2 distanceFromLocation:loc1];
    if (distance>=4) {
        NSLog(@"Very good!");
    }

}

NSLog(@"Location:%@", newLocation);
}


-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(@"Could not find location: %@", error);
}

1 个答案:

答案 0 :(得分:7)

有几点想法:

  1. 你没有考虑horizontalAccuracy。首先,如果这对任一坐标都是负的,那么你就是不能做任何比较。即使它们都是非负的,如果你真的想确定用户是否移动了一定的距离,你可能想要退出水平精度。

    不仅要查看纬度和经度,还要查看horizontalAccuracy

  2. 您不打算在开启定位服务时,经常会出现一系列坐标,当水平精度越来越好时,坐标可能会反弹。你想确保你不要把这种缓慢的三角测量视为有资格起床的必要运动。

  3. 确保您在真实场景中的真实设备上进行实验。使用模拟器绝对不是一个好的测试。也没有使用插入计算机的设备(因为您希望在真实世界的场景中看到您的GPS,有人在睡觉前移动过)。

  4. 我建议从一个简单的应用程序开始,该应用程序将位置事件记录在数据库(或其他格式)中,并可能在tableview中显示日志,因此您不必总是返回计算机审查结果。启动该应用程序,四处走动,然后查看您获得的位置事件。这可以帮助您掌握人们使用实际设备时所看到的模式。

  5. 请注意,如果此应用程序的目的地是应用程序商店,那么您将需要在不同的环境和不同的设备以及不同的场景(不良的GPS位置,无线网络,无线网络等)中吸引大量不同的人。 )。即使您使用物理设备进行自己的真实GPS体验,也必须明白其他人可能会遇到不同的GPS结果。

  6. 我必须承认iPhone GPS对于这类应用程序是否足够准确作为一种通用解决方案,你可能会警告用户确保在他们去之前插入他们的iPhone睡觉所以GPS不会耗尽电池。您可能还想玩一些技巧,例如在用户证明他们已经启动后即可启用位置服务。您可能甚至不想在闹钟响起前几分钟打开位置服务,从而确保GPS在闹钟响起时尽可能准确,但如果他们不睡觉则不会耗尽电池恰好插上电源并充电。


  7. <强>更新

    可能比自己计算距离更容易,使用位置服务距离过滤器(即仅当位置按 x 米变化时才生成事件)。例如:

    - (void)startLocationManager
    {
        self.locationManager = [[CLLocationManager alloc] init];
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
        self.locationManager.distanceFilter = 5.0; // detect when I move 5 meters
        self.locationManager.delegate = self;
        [self.locationManager startUpdatingLocation];
    }
    

    当我这样做时,完全静止不动,一旦我打开位置服务,我就会在开始移动之前得到一大堆事件。您可以看到GPS预热,并且变得越来越准确:

     latitude          longitude          horizontalAccuracy
     ----------------  ------------------ ------------------
     39.9482837548282  (82.4963494095571) 65
     39.9482817585030  (82.4964543834170) 10
     39.9482392622539  (82.4964914314290) 5
     39.9481753502422  (82.4964918505242) 5
     39.9481269028419  (82.4964797805836) 5
    

    我等不及了(在我的情况下花了15-20秒),然后我开始走直线,看着距离我上面的最后一个位置的距离。

     latitude          longitude          horizontalAccuracy distance
     ----------------  ------------------ ------------------ --------
     39.9481722908476  (82.4964962091138) 5                  5.3
     39.9482206544289  (82.4965029146363) 5                  10.4
     39.9482627315828  (82.4965282279839) 5                  15.4
     39.9483157471204  (82.4965248752227) 5                  21.2
    

    我必须承认,虽然我没有测量它,但这些距离感觉不太正确,但可能在我使用distanceFilter设置的5米容差范围内。

    无论如何,正如所有这些证据一样,正确的过程可能是

    • 启用位置服务,设置适合您应用的distanceFilter;

    • 等待该地点安定下来;

    • 确保水平准确度甚至可以使这个过程完全起作用;以及

    • 根据GPS确定已超出distanceFilter等待新位置通知。

    这永远不会是完美的(例如,在我的“5米”distanceFilter被踢之前,我必须走6-10米,这可能是GPS滞后几秒和{{1}的组合}),但它可能“对政府工作来说足够好。”

    (顺便说一下,我在上面的日志中改变了我的坐标,所以不要在这个俄亥俄州的玉米地里寻找我,但它会让你知道你可能会看到的那种模式。)