2015-04-03 28 views
3

我們的應用程序有一個過程,當用戶放大到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'

任何人都可以請幫我想出了一個替代解決方案,以確保應用程序運行流暢如沒有上述崩潰?

+0

你應該在你的主UI線程執行註釋相關的東西,而不是後臺線程,因爲註釋添加和刪除是用戶界面的更新,你應該主要做這些UI線程。 – ztan 2015-04-03 16:24:04

+0

@ztan在主UI線程中進行這些更改意味着應用程序會凍結5-10秒,除非我誤解?通過主UI線程你的意思是正常執行代碼,而不是'dispatch_async'內? – user3605739 2015-04-03 16:27:12

+0

如果你嘗試做API請求,那麼你必須在後臺線程中執行,但是你現在正在做的事情都是與UI相關的,所以你可以在主UI線程中執行它們。同時搜索你的文件,看看你是否在任何地方調用addObject方法。 – ztan 2015-04-03 16:42:19

回答

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) 
     } 
    } 
} 
+0

此代碼可能也會在[self.mapView.annotations copy]語句中崩潰,並且與該問題具有相同的異常。因此,不是一個可行的解決方案(儘管它可能會損失更少的時間) – 2016-02-17 10:11:00