看起来我遇到了一个问题,如果我在地图的可见区域被更改时添加注释,我可以可靠地导致MKMapView
崩溃。我把代码简化为一个非常简单的实现,我在这里重现它:
NSMutableArray *pointAnnotationArray = [[NSMutableArray alloc] init];
MKCoordinateRegion coordRegion = [mapViewOutlet region];
float randMax = 0.1;
for (int i = 0; i < 100; i++){
float randomDeviation1 = (((float) (arc4random() % ((unsigned)RAND_MAX + 1)) / RAND_MAX) * randMax) - (randMax / 2);
float randomDeviation2 = (((float) (arc4random() % ((unsigned)RAND_MAX + 1)) / RAND_MAX) * randMax) - (randMax / 2);
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
CLLocationCoordinate2D pointLocation = CLLocationCoordinate2DMake(coordRegion.center.latitude + randomDeviation1, coordRegion.center.longitude + randomDeviation2);
[point setCoordinate:pointLocation];
[pointAnnotationArray addObject: point];
}
[mapViewOutlet addAnnotations:[NSArray arrayWithArray:pointAnnotationArray]];
我正在做的是在地图上添加100个点,这些点在MKMapView的可见区域内和周围随机分布(足够)。重现此操作的最简单方法是将此代码设置为在计时器上运行(比如5秒后),然后抓取地图并开始放大和缩小,直到计时器运行。一旦你感觉到它,你每次都会崩溃。在mapViewOutlet
通话之前禁用addAnnotations
上的用户互动似乎没有帮助。 (也许当用户处于手势中时,它无法禁用用户交互,我认为这是可以理解的。)
我的另一个问题是我没有太多的运气跟踪崩溃 - 我没有很多经验导致崩溃直接在我自己的代码中发生,所以我可能会错过一些明显的跟踪它的方法,但我目前在return UIApplicationMain
的{{1}}行上获得了一个无用的断点。我最好的猜测是,我们在main.m
仅绘制可见注释的方式上引起了一些问题 - 缩放导致可见区域发生变化,同时添加注释并且地图正在尝试确定要绘制哪些点
有没有人见过这个?关于如何避免它的任何建议,而不是在我的注释添加的任何一端将我的地图从用户交互中锁定一段相当长的时间?
编辑:忘记包含调用堆栈:
MKMapView
答案 0 :(得分:3)
当您添加新注释时,可见注释的更改看起来像是某种问题 - 可能是MKMapView
中的一个问题,因为它可能在辅助线程中进行更新(这样看起来很挑剔) 。我要做的是回应以下两个MKMapViewDelegate
方法:
mapView:regionWillChangeAnimated:
mapView:regionDidChangeAnimated:
在第一个中,设置一个标志,指定地图被用户移动到YES
。在第二步中,将标志设置为NO
。然后,只要您想添加新注释,请检查标志。如果是NO
,那么您可以立即更新。如果是YES
,请将您的注释添加到可变集中。在mapView:regionDidChangeAnimated:
中,在清空集合之前,将该集合中的任何注释添加到地图视图中。
这应该可以解决问题,即使它不是一个优雅的解决方案。您可以在Xcode中打开断点窗格并单击添加按钮,然后选择“异常断点”,这样当您的应用程序崩溃时,您将获得确切的行,而不是main.m
。
答案 1 :(得分:1)
我有一个类似的问题,我在我的服务器中添加了一组注释并将它们从json转换为nsarray,但因为这是在后台线程中完成的,当添加和删除到mapview时我有NSGenericException,我的解决方案正在做在主线程上添加删除操作,如下所示,一切正常,即使用户正在放大,你也可以添加删除注释。但是添加时会有轻微的延迟,因为我正在尝试像1k到2k大小的数组。对于较小的东西应该没问题。
dispatch_async(dispatch_get_main_queue(),
^{
[self.mapView removeAnnotations:self.mapView.annotations];
[self.mapView addAnnotations:tempNSArray];
});