MKMapView: agregar annotations en el hilo de background

Nuestra aplicación tiene un process que se produce cuando el usuario se acerca a 1.500 pies. La razón por la que esto sucede cuando se amplía el zoom se debe al hecho de que en la región en la que se centra nuestro map hay aproximadamente 4.000 puntos de interés.

El problema que tenemos con este sistema es que cada vez que cambia la región tenemos que recorrer 4.000 puntos de interés y luego agregarlos dentro de la región que el usuario está viendo.

Este process congela la aplicación completa durante 4-5 segundos y luego agrega los POI correctos. Exploramos otras forms de hacer esto y creamos una solución para detener por completo la congelación:

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.isStarnetworkingStop(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) } } } } 

El problema con este enfoque es que creo que estamos "violando la ley". Después de hacer un poco de investigación, creo que está mal visto hacer tales processs en otro hilo. Sin embargo, incluso si ignorara ese consejo, a veces ocurren lockings.

El locking se produce en la línea 9:

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

Error:

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

¿Alguien podría ayudarme a encontrar una solución alternativa para garantizar que la aplicación funcione sin problemas como se describe arriba sin fallar?

Lo que creo que es un problema de synchronization entre subprocesss. En el subprocess de background, está intentando acceder a las annotations directamente desde la vista de map y, al mismo time, en el subprocess principal, las agrega o elimina de la vista de map.

Cambia el primer bucle for a:

 // 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) } } }