当尝试删除基于iOS 6.1的所有MKAnnotations时,MapKit上的随机崩溃。

时间:2013-08-15 00:18:35

标签: ios crash mapkit mkannotationview

使用基于iOS6.1的MapKit,当我尝试删除所有MKAnnotations然后弹出地图视图控制器时,app会随机崩溃(发生率非常低)。从崩溃日志看,它似乎是一个观察者问题,任何经历过类似问题的人都请给我一些见解,任何想法或讨论都将受到赞赏。提前致谢。

PS:

UIMapView是我应用中的单身人士,只创建一次。

2013-08-13 15:11:59.025 CHSP[9129:c07] CRASH: Cannot remove an observer <MKAnnotationContainerView 0xb8e5120> for the key path "title" from <MKUserLocation 0xbab3440> because it is not registered as an observer.

2013-08-13 15:11:59.060 CHSP[9129:c07] Stack Trace: (
    0   CoreFoundation                      0x028ff02e __exceptionPreprocess + 206
1   libobjc.A.dylib                     0x02030e7e objc_exception_throw + 44
2   CoreFoundation                      0x028fedeb +[NSException raise:format:] + 139
3   Foundation                          0x01a84a89 -[NSObject(NSKeyValueObserverRegistration) _removeObserver:forProperty:] + 790
4   Foundation                          0x01a8471d -[NSObject(NSKeyValueObserverRegistration) removeObserver:forKeyPath:] + 105
5   MapKit                              0x009194f9 -[MKAnnotationContainerView _unregisterObserverForBubbleAnnotation:] + 116
6   MapKit                              0x00919704 -[MKAnnotationContainerView setBubbleAnnotationView:] + 99
7   MapKit                              0x0091925d -[MKAnnotationContainerView _removeBubbleWithAnimation:tellDelegate:] + 247
8   MapKit                              0x0091b114 -[MKAnnotationContainerView _deselectAnnotationViewWithAnimation:tellDelegate:] + 128
9   MapKit                              0x0091b1e1 -[MKAnnotationContainerView _deselectAnnotationView] + 49
10  MapKit                              0x0092198e -[MKAnnotationContainerView _removeAnnotationView:updateCollections:] + 395
11  MapKit                              0x009217fe -[MKAnnotationContainerView _removeAnnotationView:] + 48
12  MapKit                              0x00921490 -[MKAnnotationContainerView removeAnnotation:] + 375
13  MapKit                              0x00921538 -[MKAnnotationContainerView removeAnnotations:] + 160
14  MapKit                              0x0090f8bd -[MKMapView removeAnnotations:] + 58
15  CHSP                                0x00077fd5 -[UPNewMapViewController removeAllAnnotations] + 101
16  CHSP                                0x00076640 -[UPNewMapViewController dealloc] + 64
17  UIKit                               0x01055480 -[UIViewController release] + 93
18  libobjc.A.dylib                     0x020430c3 objc_release + 51
19  libobjc.A.dylib                     0x02043bd9 _ZN12_GLOBAL__N_119AutoreleasePoolPage3popEPv + 555
20  CoreFoundation                      0x028a1468 _CFAutoreleasePoolPop + 24
21  CoreFoundation                      0x028a5afd __CFRunLoopRun + 1933
22  CoreFoundation                      0x028a4f44 CFRunLoopRunSpecific + 276
23  CoreFoundation                      0x028a4e1b CFRunLoopRunInMode + 123
24  GraphicsServices                    0x02c927e3 GSEventRunModal + 88
25  GraphicsServices                    0x02c92668 GSEventRun + 104
26  UIKit                               0x00f7753c UIApplicationMain + 1211
27  CHSP                                0x0009d9a2 main + 130
28  CHSP                                0x00002f55 start + 53
)

2013-08-13 15:11:59.061 CHSP[9129:c07] *** Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer <MKAnnotationContainerView 0xb8e5120> for the key path "title" from <MKUserLocation 0xbab3440> because it is not registered as an observer.'

2 个答案:

答案 0 :(得分:0)

由我自己修复。 最初我尝试使用另一个图像来显示用户当前位置而不是Mapkit默认位置,似乎这不是一个好主意。

答案 1 :(得分:0)

我想我发现了实际问题。 我可以按照以下顺序一致地重现问题(即使在iOS 5.1上):

1)让您的应用显示注释+用户位置

2)按主页按钮将应用程序推送到后台

3)禁用位置服务并等到应用程序真正停止(我等了60秒)

4)回到应用程序(在我的情况下,我的应用程序设置为在启动后立即更新,这将导致它在添加新注释之前尝试删除旧注释)

=&GT;这里应用程序会崩溃。

我通过自己的&#34; removeAnnotations调试它:&#34;迭代通过所有这些方法,我发现当它崩溃时,它试图删除一个比我最初添加的注释更多的注释。

如果未显示用户位置(由于其他原因导致位置服务从未启用),问题就不会发生,因此我认为这将是一种竞争,因为在上面的步骤3中禁用位置服务时,一旦发现位置服务被禁用,MKMapView将自动删除用户位置。但是,如果应用程序之前抓取了注释数组,它仍将包含用户位置,该位置由MKMapView在单独的线程中释放/销毁,因此竞争。

所以答案是你只需要删除你添加的注释。这是我的代码:

- (void)removeAnnotations
{
    NSArray *currentAnnotations = [m_MapView annotations];
    int count = [[m_MapView annotations] count];

    if (currentAnnotations && count)
    {
        NSMutableArray *annotationsToRemove = [NSMutableArray arrayWithCapacity:count];

        for (id annotation in currentAnnotations)
        {
            if ([annotation isKindOfClass:[MyAnnotation class]])
            {
                [annotationsToRemove addObject:annotation];
            }
        }

        DBGLOG(@"removeAnnotations: current_count %d, to_be_removed_count %d\n", count, [annotationsToRemove count]);

        [m_MapView removeAnnotations:annotationsToRemove];
        annotationsToRemove = nil;
    }
    currentAnnotations = nil;
    return;
}