didUpdateLocations 被调用,但发送错误的位置

Posted

技术标签:

【中文标题】didUpdateLocations 被调用,但发送错误的位置【英文标题】:didUpdateLocations gets called, but sends wrong location 【发布时间】:2013-10-14 15:23:24 【问题描述】:

我正在使用核心位置来获取 iphone 的位置。我还为我的视图控制器文件实现了委托协议,并创建了一个 CLLocationmanager 对象..

当我按下按钮 (IBAction) 时,我希望更新位置。代表被正确调用。我可以看到,因为 NSLog 消息出现在纬度/经度坐标。

但是当我在 ios 模拟器中更改位置并尝试再次使用按钮访问该位置时,我得到的位置输出保持不变。我必须再次按下按钮才能获得正确的位置。显然,我希望第一次按下按钮时位置就正确

这是我触发委托的按钮:

- (IBAction)getLocation:(id)sender 


[locationManager startUpdatingLocation];

我的 viewDidLoad 中有这段代码

locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;

这是我的委托方法:

#pragma mark - CLLocationManagerDelegate 
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error

NSLog(@"didFailWithError: %@", error);
UIAlertView *errorAlert = [[UIAlertView alloc]
                           initWithTitle:@"Error" message:@"Failed to Get Your Location" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[errorAlert show];
 

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
NSLog(@"didUpdateToLocation: %@", [locations lastObject]);
CLLocation *currentLocation = [locations lastObject];


if (currentLocation != nil) 
    _longitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude];
    _latitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude];
   
[locationManager stopUpdatingLocation];

我在 Iphone 6.1 模拟器中运行我的代码..

【问题讨论】:

只是一个注释,在 Objective C 中你可以输入 if(currentLocation) 而不是 if (currentLocation != nil)。 这是因为你只有在按下按钮时才开始更新位置,并在获得第一个位置后停止(第一个位置可能不是最准确的)。您应该保持 locationManager 更新位置。 【参考方案1】:

来自 Apple 参考资料:CLLocationManager

由于返回初始位置可能需要几秒钟,因此位置管理器通常会立即提供先前缓存的位置数据,然后在可用时提供更多最新的位置数据。

还在另一个堆栈溢出帖子 (https://***.com/questions/12858548/cllocationmanager-holds-cache-value) 中回答,使用 CLLocation 的时间戳属性过滤掉返回的较旧的缓存位置对象。我选择了 15 秒来确保区分缓存对象,但即使只有几秒钟也可能就足够了:

NSTimeInterval timeInterval = [[location timestamp] timeIntervalSinceNow];
if (abs((NSInteger)timeInterval) < 15)

    //do something

【讨论】:

如果用户更改设备的日期和时间,此解决方案将不起作用【参考方案2】:

我想通了,感谢下面其他答案的 cmets..

我在调用[locationManager stopUpdatingLocation]; 方法之前等待的时间太短了。 GPS 只是需要更多时间..

所以我只是在使用 NSTimer 执行 stopUpdatingLocation 之前等待。那完成了工作。感谢 gWiz!

【讨论】:

【参考方案3】:

我认为,已经在您的 Xcode 中设置了一个不同的位置作为模拟位置,这就是模拟器向您显示的内容。先检查一下。模拟器不会显示您当前的位置,它会显示在 Xcode 中设置的位置作为模拟位置。只有设备可以显示您的真实位置。希望对您有所帮助。

【讨论】:

这不是问题。我知道我在模拟器中输入的位置是假的。问题是当我更改这个模拟位置并通过 startUpdating 方法更新我的位置时,位置不会随之改变 然后说你从纽约到伦敦。第一次按下后显示什么?在第二个之后? 如果它没有更新,然后尝试重新启动 Xcode ,它应该可以工作。 重启 Xcode 不起作用。当我第一次从纽约换到伦敦时,它仍然显示纽约坐标。第二次坐标正确更新到伦敦【参考方案4】:

这可能是因为您尝试从didUpdateLocations 内部更新 UI,这肯定是在主线程之外的另一个线程上运行的。

改变这个:

if (currentLocation != nil) 
_longitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude];
_latitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude];

到这里:

if (currentLocation != nil) 
    dispatch_async(dispatch_get_main_queue(), ^
        _longitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude];
        _latitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude];
    );

【讨论】:

这不是位置管理器显示伪造位置的原因,但它也可能有助于更新 UI @harrym17 问题似乎只是 UI 更新,因为第二次按下按钮时会显示正确的位置。 谢谢,但这并没有改变任何东西。仍然需要按两次“获取位置”按钮才能获取我更改的位置。 尝试NSLog(@"%@", [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude]); 看看你得到了什么,以确保这不是 UI 问题。 我认为这不仅仅是一个 UI 更新问题。因为日志消息也是错误的。当我更新位置时,我的程序会输出一条日志消息,但纬度/经度坐标与之前的位置相同。只有在我第二次按下按钮时,日志消息才会更改。【参考方案5】:

在 iOS6 中尝试此代码 Apple 希望我们使用 didUpdateLocations 而不是 didUpdateToLocation

.h file


    CLLocationManager *locationManager;


.m File

  // get the current location latitude and longitude

    // locationManager update as location
    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    locationManager.distanceFilter = kCLDistanceFilterNone;
    [locationManager startUpdatingLocation];

    CLLocation *location = [locationManager location];


    locationManager.delegate=self;

    //Get user location
    [locationManager startUpdatingLocation];

    // Configure the new event with information from the location
    CLLocationCoordinate2D coordinate = [location coordinate];

    NSString *latitude = [NSString stringWithFormat:@"%f", coordinate.latitude];
    NSString *longitude = [NSString stringWithFormat:@"%f", coordinate.longitude];

    NSLog(@"dLatitude : %@", latitude);
    NSLog(@"dLongitude : %@",longitude);


- (void)locationManager:(CLLocationManager *)manager 
    didUpdateToLocation:(CLLocation *)newLocation 
           fromLocation:(CLLocation *)oldLocation

[locations lastObject];

【讨论】:

【参考方案6】:

CLLocationManager 会缓存您的位置数据。 一个有用的方法是检查更新之间的时间间隔。 您将获得每个位置更新的时间戳。 使用此比较旧的和新的位置时间戳 [newLocation.timestamp timeIntervalSinceDate:oldLocation.timestamp] 如果间隔大于 5 左右,则丢弃这些更新。

【讨论】:

以上是关于didUpdateLocations 被调用,但发送错误的位置的主要内容,如果未能解决你的问题,请参考以下文章

未调用位置管理器 didUpdateLocations

iOS - CLLocation Manager didUpdateLocations 在一个类中被调用,而不是在另一个类中?

不能调用 locationManager(_::didUpdateLocations:)

监视重大位置更改时不会调用“didUpdateLocations”

斯威夫特:我怎样才能减少 didupdatelocation 调用

如何在调用另一个方法之前等待调用 didUpdateLocations 方法?