MKMapView - 在后台线程中添加注释

时间:2015-04-03 14:59:31

标签: ios objective-c multithreading swift mapkit

我们的应用程序有一个过程,当用户放大到1500英尺时就会发生这种情况。放大这种情况的原因是由于我们的地图所关注的区域大约有4,000个兴趣点。

我们对这个系统的问题在于,每次区域更改时,我们必须循环遍历4,000个POI,然后在用户正在查看的区域内添加这些POI。

此过程冻结整个应用程序4-5秒,然后添加正确的POI。我们探索了其他方法,并提出了一个完全阻止冻结的解决方案:

func regionDidChange(mapView: MKMapView, animated: Bool) {
    if (mapView.camera!.altitude <= 1500) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
            var stopsToAdd = [StopAnnotation]()
            var stopsToRemove = [StopAnnotation]()

            // Remove old POIs
            for (var i = 0; i < self.mapView.annotations.count; i++) {
                if (self.mapView.annotations[i].isKindOfClass(StopAnnotation)) {
                    let stopAnnotation: StopAnnotation! = self.mapView.annotations[i] as StopAnnotation

                    if (!MKMapRectContainsPoint(mapView.visibleMapRect, MKMapPointForCoordinate(stopAnnotation.coordinate))) {
                        stopsToRemove.append(stopAnnotation)
                    }
                }
            }

            // Add new POIs
            for (var i = 0; i < self.busStops.count; i++) {
                if (!self.isStarredStop(self.busStops[i].atcocode)) {
                    if (MKMapRectContainsPoint(mapView.visibleMapRect, MKMapPointForCoordinate(self.busStops[i].position))) {
                        let stop: StopAnnotation! = StopAnnotation()
                        stop.setCoordinate(self.busStops[i].position)
                        stopsToAdd.append(stop)
                    }
                }
            }

            // Add new POIs to map
            dispatch_async(dispatch_get_main_queue()) {
                self.mapView.removeAnnotations(stopsToRemove)
                self.mapView.addAnnotations(stopsToAdd)
            }
        }
    }
}

这种方法存在的问题是我相信我们违反了法律规定&#34;。在做了一些研究之后,我认为在另一个线程中做这样的过程是不受欢迎的。然而,即使我忽略了这个建议,有时也会发生崩溃。

崩溃发生在第9行:

if (self.mapView.annotations[i].isKindOfClass(StopAnnotation)) {

错误:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSSetM addObject:]: object cannot be nil'

有人可以帮我提出另一种解决方案,以确保应用程序如上所述顺利运行而不会崩溃吗?

1 个答案:

答案 0 :(得分:1)

我认为这是线程之间的同步问题。在后台线程上,您尝试直接从地图视图访问注释,同时在主线程上添加/从地图视图中删除注释。

将第一个for循环更改为:

// Remove old POIs

NSArray annotations = [elf.mapView.annotations copy];
MKMapRect visibleMapRect = mapView.visibleMapRect;

for (var i = 0; i < annotations.count; i++) {
    if (annotations[i].isKindOfClass(StopAnnotation)) {
        let stopAnnotation: StopAnnotation! = annotations[i] as StopAnnotation

        if (!MKMapRectContainsPoint(visibleMapRect, MKMapPointForCoordinate(stopAnnotation.coordinate))) {
            stopsToRemove.append(stopAnnotation)
        }
    }
}