ios – 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

关于这一点的报道在网络上发生了很多变化,但许多似乎都没有得到解决.我没有做任何疯狂的事情,只是在地图上显示用户位置和一个标记.我按照我能找到的例子进行了操作,并且我已经查看了goofs的代码,但找不到任何代码.

这是我的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.按照这个速度,为什么我们不必对所有接受代表的控制都这样做?

解决方法

好的,这才是真正的答案.它来自Apple文档,但它从MKMapView中丢失了.它仅在其委托协议的文档下找到:

“在发布已设置委托的MKMapView对象之前,请记住将该对象的委托属性设置为nil.您可以在dealloc方法中处理地图视图.”

注意:这也适用于UIWebView.

我在委托的dealloc方法中将MapView的委托指针设置为nil,我们的崩溃似乎已被删除.

相关文章

UITabBarController 是 iOS 中用于管理和显示选项卡界面的一...
UITableView的重用机制避免了频繁创建和销毁单元格的开销,使...
Objective-C中,类的实例变量(instance variables)和属性(...
从内存管理的角度来看,block可以作为方法的传入参数是因为b...
WKWebView 是 iOS 开发中用于显示网页内容的组件,它是在 iO...
OC中常用的多线程编程技术: 1. NSThread NSThread是Objecti...