我有一个MKMapView
,带有一些注释,这些注释由代表用户共享其位置的代码添加。我通过websocket获得有关位置更改的更新,并更新了表示MKAnnotation
中注释的相应coordinate
。MKMapView
。
这通常效果很好,我看到用户在地图上移动。问题在于,当用户平移或缩放地图时更新MKAnnotation.cooridnate
时,MKMapView
崩溃,表示哈希表在评估时已更新。基本上是这个问题:MKMapView crashing if zooming while adding annotations
[推荐的解决方案是不对MKAnnotation.cooridnate
和MKMapView
之间的regionWillChangeAnimated
进行任何操作(例如更新我的情况下的regionDidChangeAnimated
,我正在尝试实现这一点。
问题是我的数据是通过websocket接收的,所以我不能只是“停止”监听这2个委托方法之间的新数据。从理论上讲我可以,但是那将意味着丢失一些数据,这不是解决方案。
我的想法是,我需要某种队列,将其用于将更新添加到MKAnnotation.cooridnate
,并且将在regionWillChangeAnimated
中暂停并在regionDidChangeAnimated
中恢复。
我尝试以上述方式使用DispatchQueue
,但过一会儿它会锁定。我不确定是否是因为对其添加了大量操作或对suspend
和resume
的调用。如果未锁定,则过一会儿就会使应用程序崩溃。
我的问题是什么机制在这里起作用?
如问题标题中所述,我基本上需要一种使某些方法等待条件的方法,比如说在regionWillChangeAnimated
和regionDidChangeAnimated
之间切换可靠且可以承担负载的标志。
一种方法是将这些调度到一个队列,该队列的目标是主队列:
let annotationChangeQueue = DispatchQueue(label: "...", target: .main)
通过使用主队列的目标,这意味着您可以使用此队列进行与UI相关的更改。但这也意味着您可以在区域更改正在进行时挂起该队列(不影响主队列):
func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
annotationChangeQueue.suspend()
}
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
annotationChangeQueue.resume()
}
[顺便说一句,在上面的评论中建议suspend
和resume
不起作用,因为它不会暂停正在进行的任何操作。但是因为我们使用.main
作为目标,所以绝不会与主线程上的任何内容同时发生,因此在这种情况下这不是问题。