我们的应用程序有一个过程,当用户放大到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'
有人可以帮我提出另一种解决方案,以确保应用程序如上所述顺利运行而不会崩溃吗?
答案 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)
}
}
}