0

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

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.'
4

2 回答 2

0

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

于 2013-08-23T02:49:09.817 回答
0

我想我找到了真正的问题。我可以按照以下顺序始终如一地重现该问题(即使在 iOS 5.1 上):

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

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

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

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

=> 这里应用程序将崩溃。

我通过执行我自己的“removeAnnotations:”方法通过遍历所有这些方法来调试它,我发现当它崩溃时,它试图删除比我最初添加的更多的注释。

如果未显示用户位置,则问题不会发生(或者因为从未启用位置服务,或者因为其他原因),所以我认为这将是一种竞赛,因为在上面的步骤 3)中禁用位置服务时,MKMapView 将一旦发现位置服务被禁用,就会自动删除用户位置。但是,如果应用程序之前抓取了 annotations 数组,它仍然会包含 userlocation,它正在由 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;
}
于 2013-10-05T19:29:13.697 回答