我看过其他有关此事的报道,似乎都没有适用。我们的应用程序因频繁(但不可靠的可重现性)崩溃而瘫痪:
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++;
}
}
委托是整个屏幕的控制器,因此它没有被取消分配;屏幕启动时发生崩溃。并不重要,但地图显示如下:
任何猜测或见解都会非常感激!这是在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?
对于Cocoa来说,这似乎非常混乱,在我们期望释放MapView之后,不得不将MKMapView的委托设置为nil。按照这个速度,为什么我们不必为所有接受代表的控件执行此操作?
答案 0 :(得分:10)
好的,这才是真正的答案。它来自Apple文档,但它从MKMapView中丢失了。它只能在其委托协议的文档中找到:
“在释放已设置委托的MKMapView对象之前,请记住将该对象的委托属性设置为nil。您可以在dealloc方法中处理地图视图。”
注意:这也适用于UIWebView。
我在委托的dealloc方法中将MapView的委托指针设置为nil,我们的崩溃似乎已被删除。
答案 1 :(得分:2)
我有类似的问题,我尝试过你的解决方案来设置我的mapView.delegate=nil
,但它只适用于第一次重绘mapview时。在第二次崩溃之后。
在我的情况下,错误发生在这一行。
[CLPlacemark dealloc]
我的'StashMarker'来自MKPlacemark。 所以我只是改变了'StashMarker'的构造函数 从这个
self = [super init];
到此
self = [super initWithCoordinate:your_coord addressDictionary:[NSDictionary dictionary]];
CLPlacemark是MKPlacemark的父级,您的Annotation类需要发布'addressDictionary'。
答案 2 :(得分: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];
同样,这可能与您遇到的崩溃无关。