【问题标题】:didUpdateLocations gets called, but sends wrong locationdidUpdateLocations 被调用,但发送错误的位置
【发布时间】: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 更新位置。

标签: iphone ios objective-c


【解决方案1】:

来自 Apple 参考资料:CLLocationManager

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

还在另一个堆栈溢出帖子 (https://stackoverflow.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 左右,则丢弃这些更新。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-09-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-26
        • 2016-05-29
        • 1970-01-01
        相关资源
        最近更新 更多