【问题标题】:iOS MapKit crashing through didUpdateUserLocation - bafflediOS MapKit 通过 didUpdateUserLocation 崩溃 - 困惑
【发布时间】:2024-01-13 14:20:01
【问题描述】:

我需要一些关于我正在使用 MapKit 制作的应用程序的帮助

我正在为 didUpdateUserLocation 苦苦挣扎: - 它不断随机地使应用程序崩溃。当我注释掉所有代码时,它工作得很好,但这不是一个合适的情况。我一直在摆弄它,但仍然没有真正的成功。

这是我的代码

-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
    NSLog(@"update loc");
    MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 250.0, 250.0);//MKCoordinateRegionMake(userLocation.coordinate, mapView.region.span);
    if (first) {
        region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 250.0, 250.0);
        first = false;
    }
    if (!CLLocationCoordinate2DIsValid(userLocation.coordinate)) {
        //do nothing, invalid regions
        NSLog(@"co-ord fail");
    } else if (region.span.latitudeDelta <= 0.0 || region.span.longitudeDelta <= 0.0) {
        NSLog(@"invalid reg");
    } else {
        [mapView setRegion:region animated:NO];
    }
} 

该应用永远不会遇到“co-ord fail”或“invalid reg”,所以我真的不知道问题出在哪里,因为我自己设置了这些值。

该问题通常发生在 Map 的 nib 关闭并释放视图时。

我看到了其他一些建议,但对他们的工作没有信心。理想情况下,我想使用 mapView.region.span 来保持缩放级别

非常感谢, 詹姆斯

【问题讨论】:

  • 崩溃时的确切错误信息是什么?
  • 抱歉没有看到这个——这里有点菜鸟。在调试时没有特定的错误代码,但在崩溃日志中,崩溃的解释是 [MapKit mapView:didUpdateUserLocation:]。我已经使用达里尔回答的指导解决了这个问题。感谢您的回复!

标签: ios map mapkit region


【解决方案1】:

请注意,如果一个应用程序暂停了一小会儿,在恢复时

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation 

delegate 作为第一个 userLocation (0.0,0.0) 接收纬度,经度!我认为这是一个错误..检查:

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
NSLog( @"userLocation:(%p) %@",userLocation,userLocation);
NSLog( @"userLocation.location:(%p) %@",userLocation.location,userLocation.location);
NSLog( @"userLocation.coordinate: %f,%f valid:%d",userLocation.coordinate.latitude,userLocation.coordinate.longitude,  CLLocationCoordinate2DIsValid(userLocation.coordinate));
NSLog( @"userLocation.location.coordinate: %f,%f valid: %d",userLocation.location.coordinate.latitude,userLocation.location.coordinate.longitude, CLLocationCoordinate2DIsValid(userLocation.location.coordinate));

结果:

userLocation:(0x193fc0) <MKUserLocation: 0x193fc0>
userLocation.location:(0x0) (null)
userLocation.coordinate: -180.000000,-180.000000 valid:0
userLocation.location.coordinate: 0.000000,0.000000 valid: 1

奇怪的是,0,0 是从 userLocation.location.coordinate 产生的,而 userLocation.location 是 nil,产生一个有效的坐标,甚至!

确实,检查 userLocation.location 是否为 nil 似乎最好。

【讨论】:

  • 感谢您的评论,这已包含在 CLLocationCoordinate2DIsValid() 检查中
  • 我不认为 CLLocationCoordinate2DIsValid 捕获 0,0(见上文)
  • 最好使用if (userLocation.location == nil) 而不是检查技术上有效的坐标 0,0。
  • 啊,我(曾经)使用的是 userLocation.location.coordinate,而不是 userLocation.coordinate!现在我很困惑,MKUserLocation 有一个属性“位置”,它本身也有一个属性“坐标”。 MKUserLocation 本身也有一个坐标,它是从 MKAnnotation 继承而来的……正在研究有什么区别……
  • 在 Objective-C 中,当您向 nil 对象发送消息时,您会返回 0(而不是崩溃),这就是 location.coordinate 的 NSLog 具有误导性的原因。但是,我认为这与 OP 的问题无关。
【解决方案2】:

这个问题通常发生在地图的笔尖关闭并且它 已解除分配视图。

   [mapView setRegion:region animated:NO];

那这不是你的问题吗?

这就是为什么我们有像 Observer/Listener 这样的依赖倒置模式。

不要直接使用您的 CLLocationManager 委托来摆弄视图,而是使用 NSNotification 来提醒订阅视图(例如您的 MapView)它应该更新。如果 MapView 已被释放,它不会做任何事情。

【讨论】:

  • -(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation 是委托调用的一部分,所以它只被 MKMapView 调用,所以我不认为 N​​SNotification 是正确的方法。但是,您确实让我思考(根据您的正确想法,即 MapView 将被释放,我应该检查 nob 哈希是否已释放)并且我意识到我应该从 dealloc 中释放 MapView。这似乎提供了一个解决方案。感谢您的指导!!