2012-12-17 33 views
1

看起來我正遇到一個問題,即如果在地圖的可見區域正在更改時添加註釋,我可以可靠地導致我的MKMapView崩潰。我煮,是造成它歸結爲一個非常簡單的實現代碼,我在這裏重現它:如果在添加註釋時縮放MKMapView會崩潰

NSMutableArray *pointAnnotationArray = [[NSMutableArray alloc] init]; 
MKCoordinateRegion coordRegion = [mapViewOutlet region]; 
float randMax = 0.1; 

for (int i = 0; i < 100; i++){ 
    float randomDeviation1 = (((float) (arc4random() % ((unsigned)RAND_MAX + 1))/RAND_MAX) * randMax) - (randMax/2); 
    float randomDeviation2 = (((float) (arc4random() % ((unsigned)RAND_MAX + 1))/RAND_MAX) * randMax) - (randMax/2); 

    MKPointAnnotation *point = [[MKPointAnnotation alloc] init];   
    CLLocationCoordinate2D pointLocation = CLLocationCoordinate2DMake(coordRegion.center.latitude + randomDeviation1, coordRegion.center.longitude + randomDeviation2); 
    [point setCoordinate:pointLocation];  
    [pointAnnotationArray addObject: point]; 
} 

[mapViewOutlet addAnnotations:[NSArray arrayWithArray:pointAnnotationArray]]; 

我在做什麼上面是隨機分佈在地圖上添加100分(足夠)在MKMapView的可見區域內和周圍。最簡單的方法是將此代碼設置爲在定時器上運行(例如5秒後),然後抓取地圖並開始放大和縮小,直到定時器運行。一旦你感覺到它,你可以每次都會發生崩潰。調用addAnnotations之前在mapViewOutlet上禁用用戶交互似乎沒有幫助。 (也許這是不能禁用用戶交互,而用戶是中間手勢,這是可以理解的,我想。)

我的其他問題是,我沒有太多的運氣追蹤崩潰 - 我不有很多經驗導致不會直接在我自己的代碼中發生崩潰,所以我可能會錯過一些顯而易見的方式來跟蹤它,但我目前在main.mreturn UIApplicationMain行上獲得無益的斷點。我最好的猜測是,我們在MKMapView只繪製可見註釋方面引發了一些問題 - 縮放導致可見區域發生變化,同時添加註釋並且地圖試圖確定繪製哪些點。

有沒有其他人看到過這個?有關如何避免它的任何建議,而無需將我的地圖從用戶交互鎖定在我的註釋添加的任何一端的相當長的時間?

編輯:忘了包括調用堆棧:

#0 0x3752a944 in objc_exception_throw() 
#1 0x3869dec0 in __NSFastEnumerationMutationHandler() 
#2 0x31929d46 in -[MKAnnotationContainerView _updateAnnotationViewPerspective]() 
#3 0x3192981a in -[MKMapView _updateScrollContainerView:]() 
#4 0x3192ff66 in -[MKMapView mapViewDidDraw:]() 
#5 0x391560b4 in -[VKMapCanvas didDrawView]() 
#6 0x3914d4a8 in -[VKScreenCanvas onTimerFired:]() 
#7 0x3914b4a8 in -[VKMapCanvas onTimerFired:]() 
#8 0x3914a346 in -[VKMainLoop displayTimerFired:]() 
#9 0x35ebe780 in CA::Display::DisplayLink::dispatch(unsigned long long, unsigned long long)() 
#10 0x35ebe6d8 in CA::Display::IOMFBDisplayLink::callback(__IOMobileFramebuffer*, unsigned long long, unsigned long long, unsigned long long, void*)() 
#11 0x34815fd6 in IOMobileFramebufferVsyncNotifyFunc() 
#12 0x370315ac in IODispatchCalloutFromCFMessage() 
#13 0x3866888a in __CFMachPortPerform() 
#14 0x386733e6 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__() 
#15 0x3867338a in __CFRunLoopDoSource1() 
#16 0x3867220e in __CFRunLoopRun() 
#17 0x385e523c in CFRunLoopRunSpecific() 
#18 0x385e50c8 in CFRunLoopRunInMode() 
#19 0x3591e33a in GSEventRunModal() 
#20 0x379d5290 in UIApplicationMain() 
#21 0x0005aff4 in main at /Users/Sydin/App/main.m:16 

回答

3

它看起來像某種問題,更改可見的註釋,當你添加新的 - 可能是MKMapView一個問題,因爲它可能是在一個輔助線程中進行更新(這是非常挑剔的)。我會做的是以下兩個MKMapViewDelegate方法作出迴應:

  • mapView:regionWillChangeAnimated:
  • mapView:regionDidChangeAnimated:

在第一個,設置一個標誌,指定該地圖由用戶移動到YES。在第二個中,將標誌設置爲NO。然後,每當你想添加新的註釋,檢查標誌。如果是NO,那麼你馬上就可以更新。如果是YES,請將您的註釋添加到可變集。在mapView:regionDidChangeAnimated:中,在清空集合之前,將該集合中的所有註釋添加到地圖視圖中。

這應該解決問題,即使它不是一個優雅的解決方案。您可以在Xcode中打開斷點窗格,然後單擊添加按鈕,然後選擇「異常斷點」,以便在應用程序崩潰時獲得確切的行,而不是main.m

+0

感謝您的建議;這確實是訣竅。另外,我應該更加明確,但是我在測試中使用了異常斷點,這就是爲什麼我不能獲得關於異常的更多信息的原因。 – Sydin

1

我有一個類似的問題,我添加一組註釋從我的服務器獲取並將它們從json轉換爲nsarray,但因爲這是在後臺線程中添加和刪除mapview時我有NSGenericException,我的解決方案是在下面的主線程中添加刪除操作,並且所有操作都可以正常工作,即使用戶放大時也可以添加刪除註釋。但是在添加時會有輕微的延遲,因爲我正在嘗試像1k到2k大小的陣列。對於較小的東西應該沒問題。

dispatch_async(dispatch_get_main_queue(), 
^{ 
     [self.mapView removeAnnotations:self.mapView.annotations]; 
     [self.mapView addAnnotations:tempNSArray]; 

    });