2011-11-16 102 views
3

我已經看過其他報告,似乎沒有適用。我們的應用程序正在被削弱頻繁(但並不可靠重複性)崩潰這樣的:在MKMapView annotationContainer中持續崩潰:viewForAnnotation

Thread 0 name: Dispatch queue: com.apple.main-thread 
Thread 0 Crashed: 
0 libobjc.A.dylib     0x333a6c98 objc_msgSend + 16 
1 MapKit       0x30be52fc -[MKMapView annotationContainer:viewForAnnotation:] + 36 
2 MapKit       0x30be4f8e -[MKAnnotationContainerView _addViewForAnnotation:] + 270 
3 MapKit       0x30c0f164 -[MKAnnotationContainerView addViewForManagedAnnotation:notifyDelegate:] + 12 
4 MapKit       0x30c0b874 -[MKMapView(UserPositioningInternal) _runPositioningChange] + 1036 
5 MapKit       0x30c09a86 -[MKMapView(UserPositioningInternal) _startPositioningChange:] + 22 
6 MapKit       0x30c0d04a -[MKMapView(UserPositioningInternal) locationManagerUpdatedLocation:] + 578 
7 CoreFoundation     0x360bcefc -[NSObject(NSObject) performSelector:withObject:] + 16 
8 CoreFoundation     0x360fa2f2 -[NSArray makeObjectsPerformSelector:withObject:] + 394 
9 MapKit       0x30bfc802 -[MKLocationManager _reportLocationStatus:] + 34 
10 MapKit       0x30bfdd6c -[MKLocationManager _reportLocationSuccess] + 36 
11 MapKit       0x30bfd9c6 -[MKLocationManager locationManager:didUpdateToLocation:fromLocation:] + 674 

的這個報告帶來很多在網絡上,但很多似乎去解決。我沒有做任何瘋狂的事情,只是在地圖上顯示用戶的位置和一個標記。我跟着我可以找到的例子,我已經看過代碼,但找不到任何代碼。

這裏是我的MapView代表如何處理viewForAnnotation:

- (MKAnnotationView*)mapView:(MKMapView*)theMapView viewForAnnotation:(id <MKAnnotation>)annotation 
{ 
    // If it's the user location, just return nil. 
    if([annotation isKindOfClass:[MKUserLocation class]]) 
    { 
     return nil;  // Use default system user-location view. 
    } 
    else 
    { 
     // Try to dequeue an existing pin view first. 
     MKPinAnnotationView* pinView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:@"stashMarkerID"]; 
     if(!pinView) 
     { 
      // If an existing pin view was not available, create one. 
      pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation 
                 reuseIdentifier:@"stashMarkerID"] autorelease]; 
      pinView.pinColor = MKPinAnnotationColorPurple; 
      pinView.animatesDrop = YES; 
      pinView.canShowCallout = NO; 
     } 
     else 
     { 
      pinView.annotation = annotation; 
     } 

     return pinView; 
    } 
} 

崩潰,似乎與用戶的位置的變化有關,但一旦用戶位置標記添加的,我不惹它。當我需要刷新另一個地圖標記,我刪除了另一個時跳過用戶標記:

// Add the marker to the map. 
// Remove old one(s) first. 
int i = 0; 
while(i < [mapView.annotations count]) 
{ 
    if ([[mapView.annotations objectAtIndex:i] isKindOfClass:[StashMarker class]]) 
    { 
     [mapView removeAnnotation:[mapView.annotations objectAtIndex:i]]; 
    } 
    else 
    { 
     i++; 
    } 
} 

的代表是整個屏幕控制器,所以它沒有被釋放;在屏幕啓動時發生崩潰。這不是問題,但地圖顯示的信息如下:

enter image description here

任何猜測或洞察力將不勝感激!這是在iOS 5.0.1上。

更新:我們發現,當沒有MKMapView甚至存在時,發生這種崩潰。包含它的視圖早已被彈出。我在想,如果我們遇到此報告的問題:MKMapView crashes app when view controller popped

更新2:這裏有一個本質上是一回事另一份報告:Why am I crashing after MKMapView is freed if I'm no longer using it?

這似乎可可異常凌亂,具有的MKMapView的委託後設置爲零我們期望MapView被釋放。按照這個速度,爲什麼我們不需要爲接受委託的所有控制執行此操作?

+0

在未來的問題中,請不要發佈代碼和日誌的截圖。相反,請複製並粘貼文字。 – Anna

+0

你在使用CLLocationManager嗎?刪除註釋的代碼是什麼方法(我會採用不同的方式)?該代碼之前或之後做了什麼?你在didUpdateUserLocation或didUpdateToLocation委託方法中有什麼代碼? – Anna

+0

你將如何刪除註釋不同? – Oscar

回答

10

好的,這是真正的答案。它來自蘋果文檔,但它從MKMapView中丟失。只有在其代理協議的文檔中才能找到它:

「在釋放已設置委託的MKMapView對象之前,請記住將該對象的委託屬性設置爲nil。一個可以執行此操作的位置在dealloc方法中你在那裏處理地圖視圖。「

注意:這也適用於UIWebView。

我在代理的dealloc方法中將MapView的委託指針設置爲nil,並且我們的崩潰似乎已被消除。

+0

嗯,很酷,我會測試一下。看起來不痛,嘗試它。即使看起來像正確的做事方式:) –

+1

嗡嗡聲,okey。在啓用位置更新的情況下在MapView上滾動時,我的應用程序用於在30秒(或以上)內隨機崩潰,並顯示類似的堆棧跟蹤。現在我已經將代理設置爲無視圖控制器dealloc的我已經能夠在5分鐘內滾動而沒有任何問題。看起來不錯,謝謝。 –

0

(免責聲明:我不知道這是否是導致您的問題)

在評論,我說:

我會通過將那些刪除刪除註釋到另一個 數組,然後調用removeAnnotations(複數)而不是在原地移除 ,並使用特定索引來引用註釋。

,你問:

有什麼特別的原因,你更喜歡收集註釋 撈出做一次全部?

實際上,它並不是一次全部刪除的部分,而是依賴於數組索引。

我不希望假設我在一行上得到的索引i的註釋在其他時間(即使是下一行)仍然存在,即使我的代碼沒有添加或刪除其中的任何註釋。

地圖視圖(我認爲)只是將註釋列表作爲一個數組提供給我們,這是爲了方便,但它在內部可能會以不同方式存儲列表,並且可能會混淆內容(但不會更改註釋引用)。

我覺得更安全的是不要認爲annotations數組內容將保持在固定位置。

所以只刪除某些註釋,我更喜歡這樣的:

NSMutableArray *annotationsToRemove = [NSMutableArray array]; 

for (id<MKAnnotation> ann in mapView.annotations) 
{ 
    if ([ann isKindOfClass:[StashMarker class]]) 
    { 
     [annotationsToRemove addObject:ann]; 
    } 
} 

[mapView removeAnnotations:annotationsToRemove]; 

同樣,這可能無關,與您所遇到的崩潰。

+0

謝謝安娜。我確實嘗試切換到上面概述的方法,但這個東西仍然崩潰。我想知道MapView是否可以調用viewForAnnotation來獲取已被刪除的註釋。我猜想唯一的辦法就是在修改註釋的代碼部分和委託的viewForAnnotation方法中加鎖。在viewForAnnotation中,我可以在MapView的註釋中搜索我應該提供的視圖,以確保它仍然存在。我不知道現在還有什麼要做。這是一個很大的錯誤。 – Oscar

+0

您是否嘗試禁用showsUserLocation以查看它是否確實與此相關?嘗試開始一個新項目並一次添加一個函數,直到重現崩潰。或者從當前代碼一次一個地註釋掉一個函數,直到崩潰停止爲止。 – Anna

+0

我從其他地方的調查結果更新了這個問題。看起來MKMapViews在你期望它們被釋放之後四處遊蕩,調用早已被銷燬的代表。 – Oscar

2

我有類似的問題,我試過你的解決方案來設置我的mapView.delegate=nil但它只適用於我第一次重繪mapview。第二次崩潰後。 在我的情況下,錯誤發生在這條線。 [CLPlacemark dealloc]

而我的'StashMarker'則來源於MKPlacemark。 於是我就改變我的「StashMarker」 構造從這

self = [super init]; 

對此

self = [super initWithCoordinate:your_coord addressDictionary:[NSDictionary dictionary]]; 

CLPlacemark這是MKPlacemark的父母和你的註解類需要一個「addressDictionary」被釋放。