答案是您需要按照您希望的方式编写处理。
我已经阅读了这个常见问题。我应该澄清一下,“强制”意味着开始明确的行为,在手机的最佳条件下提供可靠的位置。不要忙于等待直到满意或期望立即得到结果/错误代码。
从常识的角度来看,所有开发人员都希望至少有一种额外的方法来简单地请求参数中的位置,并且仅在其有效且在准确性范围内、取消或超时时才回调。如果条件阻止它,那么您无需测试深奥的行为即可使用自定义代码处理它。
为什么我需要问这个问题是:
不存在上述功能的方法
使用书中的代码(更多 Iphone 3 开发)
从头开始编写时(查看 LocateMe.xproj),发现:
模拟器行为与电话行为不同(不是谈论位置本身,这显然与 ip 查找一样好,而是 didUpdateToLocation 的行为)。认识到模拟器的局限性,该方法至少应该像在设备上那样运行。但是目前,正确编写的位置处理/检查代码只是在模拟器中超时(如在 LocateMe 示例中),而错误代码(询问一次并在回调中使用 newLocation)可以正常工作。
以及导致 [locationManager stopUpdatingLocation] 之后两次调用 didUpdateToLocation 的错误;
如果除此之外,您(像我一样)根据您的位置加载数据,并且应用程序中的多个视图都需要数据,那么 Apple 的位置获取方法的行为并不容易处理更新链 - load-calculate-present 在整个应用程序中始终如一且没有问题。特别是如果您在用户/老板的看法或决定它应该如何工作(一块石头)和系统如何工作(一个困难的地方)之间陷入困境。
这是我当前在设备和模拟器上运行的代码:
//ask for a position, as fresh as possible.
-(void)updateMeMap {
lastloc.coordinate=homeloc.coordinate;
lm.delegate=self;
ctr=0;
[self performSelector:@selector(stopUpd) withObject:nil afterDelay:gpstimeout];
[lm startUpdatingLocation];
}
//called on each position update.
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
ctr++;
if (ctr<15) {
NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];
NSLog(@"%d",ctr);
if (locationAge<60) {
NSLog(@"Found");
ctr=40;
homeloc.coordinate=newLocation.coordinate;
[self stopUpd];
[self reload];
} else {
NSLog(@"Lastupd");
lastloc.coordinate=newLocation.coordinate;
}
} else {
//enough tries, if not canceled choose lastloc.
if (ctr<40) {
NSLog(@"Last");
ctr=40;
homeloc.coordinate=lastloc.coordinate;
[self stopUpd];
[self reload];
}
}
}
//force stop updates. ctr prevents extra calls after stopUpdatingLocation.
//called after the timeout delay, if position found, cancel the timeout.
-(void)stopUpd {
[lm stopUpdatingLocation];
lm.delegate=nil;
if (ctr<15) {
ctr=40; //2 extra calls after stopupda... otherwise, now do nothing.
NSLog(@"Timeout");
homeloc.coordinate=lastloc.coordinate; //@need "copy"?
[self reload];
} else {
ctr=40; //2 extra calls after stopupda... otherwise, now do nothing.
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(stopUpd) object:nil];
}
}
// "couldn't get userlocation" handler. I also cancel like this on connectionDidFailWithError.
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog(@"Location failed: %@",[error localizedDescription]);
ctr=0;
[self stopUpd];
}
其中 ctr 是为了防止 2 次额外调用,lastloc 是最后已知的可靠位置,homeloc 是用于(线程)加载具有 [self reload] 的位置特定数据的电话位置。
常数 15 和 60 是来自实际测试的安全值;gpstimeout 设置为 30。如果您在模拟器中工作很多,您可能希望将其设置为 3 秒之类的短时间,因为您将得到的只是一个陈旧但相对可用的位置,并且在超时之前不会更多。
编辑:如果您能最好地使用我的代码或指出一个遗漏,我会将其标记为答案,我讨厌将我自己的代码标记为答案。