2

我正在制作一个警报,该警报仅在手机移动一定距离后才会关闭(以迫使用户下床)。我需要能够在警报响起后找到行进的距离,然后获取此距离并在已行进最小距离时将其用于关闭警报声音的方法。有任何想法吗?我正在使用以下内容来更新位置。关于如何将其纳入禁用警报的任何想法?

-(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);
}
4

1 回答 1

7

几个想法:

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

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

  2. 你没有考虑到,当你打开定位服务时,经常会有一整串坐标进来,随着水平精度越来越好,坐标可能会反弹。您要确保不要将这种缓慢的三角测量视为有资格起床所需的运动。

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

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

  5. 请注意,如果此应用程序是为应用程序商店而设计的,您将需要在不同的环境、不同的设备和不同的场景(GPS 位置不佳、有 wifi、没有 wifi 等)中吸引许多不同的人。即使您使用物理设备进行自己的真实 GPS 体验,您也必须意识到其他人可能会体验到不同的 GPS 结果。

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


更新:

可能比自己计算距离更容易,使用位置服务距离过滤器(即仅在位置变化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 正在升温,并且越来越准确:

纬度经度水平精度
 ---------------- ------------------ ---------------- --
 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 秒),然后我开始直线行走,看着距离上一个位置的距离。

纬度经度水平精度距离
 ---------------- ------------------ ---------------- ----------
 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.

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

  • 打开位置服务,设置distanceFilter适合您的应用程序;

  • 等待地点安定下来;

  • 确保 Horizo​​ntalAccuracy 甚至是合理的,这个过程完全可以工作;和

  • 等待基于 GPS 确定distanceFilter已超过的新位置通知。

这永远不会是完美的(例如,在我的“5 米”开始之前,我必须步行 6 到 10 米,可能distanceFilter是 GPS 滞后几秒钟和horizontalAccuracy。”

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

于 2013-02-25T02:53:55.790 回答