我们的应用程序有一个过程,当用户放大到1500英尺时发生这种情况发生在放大时发生这种情况是因为我们的地图在那里聚焦的区域大约有4000个兴趣点。MKMapView - 在后台线程中添加注释
我们在这个系统中遇到的问题是,每当区域发生变化,我们都必须循环4000个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)
}
}
}
}
这种方法的问题是,我相信我们“犯法”。在做了一些研究之后,我认为在另一个线程中做这样的过程令人不敢恭维。但即使我不理睬这些建议,有时候也会发生崩溃。
崩溃发生在9号线:
if (self.mapView.annotations[i].isKindOfClass(StopAnnotation)) {
错误:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSSetM addObject:]: object cannot be nil'
任何人都可以请帮我想出了一个替代解决方案,以确保应用程序运行流畅如没有上述崩溃?
你应该在你的主UI线程执行注释相关的东西,而不是后台线程,因为注释添加和删除是用户界面的更新,你应该主要做这些UI线程。 – ztan 2015-04-03 16:24:04
@ztan在主UI线程中进行这些更改意味着应用程序会冻结5-10秒,除非我误解?通过主UI线程你的意思是正常执行代码,而不是'dispatch_async'内? – user3605739 2015-04-03 16:27:12
如果你尝试做API请求,那么你必须在后台线程中执行,但是你现在正在做的事情都是与UI相关的,所以你可以在主UI线程中执行它们。同时搜索你的文件,看看你是否在任何地方调用addObject方法。 – ztan 2015-04-03 16:42:19