jsk*_*dd3 2 xcode ios swift xcode6
func mapView(mapView: MKMapView!, regionDidChangeAnimated animated: Bool) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
if (self.busStops.count > 0) {
if (mapView.camera!.altitude <= 1000) {
for (var i = 0; i < self.busStops.count; i++) {
if (MKMapRectContainsPoint(mapView.visibleMapRect, MKMapPointForCoordinate(self.busStops[i].position))) {
let stop = BusAnno()
stop.setCoordinate(self.busStops[i].position)
stop.type = "stop"
stop.title = self.busStops[i].name
stop.subtitle = self.busStops[i].street
self.activeStops.append(stop)
}
}
dispatch_async(dispatch_get_main_queue()) {
self.mapView.addAnnotations(self.activeStops)
}
} else if (self.activeStops.count > 0) {
mapView.removeAnnotations(self.activeStops)
self.activeStops = []
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码目前给了我:
Terminating app due to uncaught exception 'NSGenericException',
reason: '*** Collection <__NSArrayM: 0x1775edd0> was mutated while being enumerated.'
Run Code Online (Sandbox Code Playgroud)
发生这种情况的原因是,如果用户在应用程序仍然添加公交车站时快速缩小,则会提交"被枚举时发生变异"错误.问题是,我不知道如何解决这个问题,我基本上需要检查应用程序是否已经完成添加公交车站,然后再删除它们.
此代码的目的是在放大小于1000米时向地图添加公交车站,然后在高于此高度时移除公交车站而不会出现此错误.
该问题涉及线程安全.您的busStops数组正在被2个线程同时修改.
因此,您需要同步对它的访问,即确保您对busStops阵列的更新是连续发生的(一个接一个),而不是同时发生(同时发生).一种方法是将该数组的所有修改分配给您创建的串行队列.
dispatch_get_global_queue将上述逻辑分派给全局共享并发队列.而不是使用全局队列,创建自己的队列并将其存储在类的实例变量中.
_queue = dispatch_queue_create("com.app.serialQueue", DISPATCH_QUEUE_SERIAL);
Run Code Online (Sandbox Code Playgroud)
然后根据需要向其发送工作:
dispatch_async(_queue, ^{
// Work, i.e. modifications to busStops array
});
Run Code Online (Sandbox Code Playgroud)
如果您希望获得更多细微差别,可以将队列设置为并发队列,并dispatch_async用于对busStops阵列的所有读取,并dispatch_barrier_async用于所有写入.后者实质上使队列暂时表现为串行队列.
我担心"被点名时变异"并不是你最大的问题.您也快速连续启动新线程,因为mapView:regionDidChange:可以在缩放/平移期间快速连续调用.从课程参考:
只要当前显示的地图区域发生变化,就会调用此方法.在滚动期间,可以多次调用此方法以报告对地图位置的更新.
因此,您还要多次向地图添加相同的注释.
您的算法应该类似于以下内容.请注意,这只是一个草图,它不处理删除,它可能甚至不是有效的Swift,我从来没有用语言编程:
func mapView(mapView: MKMapView!, regionDidChangeAnimated animated: Bool) {
if (isUpdating) {
return;
isUpdating = true;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
var currentRect;
do {
currentRect = mapView.visibleMapRect;
var toAdd = [];
for (var i = 0; i < self.busStops.count; i++) {
if (!self.busStops[i].isOnMap && MKMapRectContainsPoint(currentRect, MKMapPointForCoordinate(self.busStops[i].position))) {
// create stop
toAdd.append(stop);
self.busStops[i].isOnMap = true;
}
}
dispatch_async(dispatch_get_main_queue()) {
self.mapView.addAnnotations(toAdd)
}
} while (mapView.visibleMapRect != currentRect);
isUpdating = false;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3606 次 |
| 最近记录: |