在我的应用程序中,我需要知道用户位置,然后从数据库加载数组 . 所以我创建了一个CLLocationManager实例
@property (nonatomic,strong) CLLocationManager *gps;
在viewDidLoad中我设置了gps的一些属性:
- (void)viewDidLoad
{
[super viewDidLoad];
self.gps = [[CLLocationManager alloc] init];
self.gps.delegate = self;
self.gps.desiredAccuracy = kCLLocationAccuracyBest;
}
并在viewDidAppear中,如果我的表视图为空,我开始更新用户位置:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if ([self.tableView numberOfRowsInSection:0] <= 0) {
[self.gps startUpdatingLocation];
}
}
现在,当gps找到用户位置时,它会调用委托方法:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(@"DID UPDATE LOCATIONS");
[self.gps stopUpdatingLocation];
if (!didUpdateLocation) {
didUpdateLocation = YES;
currentLocation = [locations lastObject];
[self performSelectorOnMainThread:@selector(loadDistance) withObject:nil waitUntilDone:YES];
[self caricaLocaliInOrdineAlfabetico:NO];
}
}
问题在于委托方法导致SOMETIMES(并非总是),即使我要求gps停止更新位置,也会多次调用它 . 正如您所看到的,我还尝试声明一个名为didUpdateLocation的BOOL,以检查用户位置是否已被占用,但似乎没用 . 怎么可能?
这是调试日志:
2014-05-05 18:22:02.324 AppName[9529:60b] <FMDatabase: 0x16d5e740> executeQuery: SELECT * FROM locali
2014-05-05 18:22:02.483 AppName[9529:60b] DID UPDATE LOCATIONS
2014-05-05 18:22:06.002 AppName[9529:60b] CARICA LOCALI
2014-05-05 18:22:06.005 AppName[9529:60b] LOCALE INDEX: 170
2014-05-05 18:22:06.009 AppName[9529:60b] <FMDatabase: 0x16e6b040> executeQuery: SELECT * FROM locali ORDER BY distanza ASC
2014-05-05 18:22:06.068 AppName[9529:60b] DID UPDATE LOCATIONS
2014-05-05 18:22:09.784 AppName[9529:60b] CARICA LOCALI
2014-05-05 18:22:09.791 AppName[9529:60b] LOCALE INDEX: 170
2014-05-05 18:22:09.802 AppName[9529:60b] <FMDatabase: 0x16e72130> executeQuery: SELECT * FROM locali ORDER BY distanza ASC
3 回答
你的前提是有缺陷的 .
当您首次要求更新位置时,位置管理会产生非常糟糕的结果,并需要一段时间才能安定下来并开始提供良好的结果 .
您不能只读取一个位置,并认为它是一个准确的位置 . 大多数情况下,这将是非常不准确的 .
您需要检查位置更新的时间戳,并拒绝超过几秒钟的更新 . 这是因为位置管理器缓存了GPS上次运行时读取的位置,有时会给您第一个读取数小时或数天的位置,并且可能非常错误 .
接下来,您将开始获得水平精度非常差的读数 . 前几个读数可能会偏离一公里或更多 . 您需要进行更新,直到获得足够准确的更新为止 . (精度读数实际上是一个半径值,表示读数中可能存在的误差 . )
您需要对您的位置更新进行编码以丢弃不准确的读数,并且如果您在合理的时间内没有获得满意的读数,最终会超时(30秒将是一个很好的起点 . )
只有当您获得具有最近时间戳并具有足够低的准确度读数的读数时,才应处理读数 . 此时,设置“didUpdateLocation”标志并停止位置更新 .
它不是一个bug .
didUpdateLocations:在调用stopUpdatingLocation后可以继续调用,所以你应该为此编写代码 .
我认为避免这个问题的最好方法是使用计时器 . 现在,即使多次调用委托方法,也没有问题 .
在.h文件中
在.m文件中
正如DuncanC所说,从gps获取的第一个位置可能不准确,因此我从horizontalAccuracy和verticalAccuracy计算平均精度,以提高当前位置的准确性 .