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

私は実際の問題を見つけたと思います。次の手順で、(iOS 5.1 でも) 問題を一貫して再現できます。

1) アプリに注釈とユーザーの位置を表示させる

2) ホームボタンを押して、アプリをバックグラウンドにプッシュします

3) 位置情報サービスを無効にして、アプリが実際に停止するまで待ちます (私は 60 秒待ちました)

4)アプリに戻ります(私の場合、アプリは起動するとすぐに更新するように設定されていたため、新しい注釈を追加する前に古い注釈を削除しようとします)

=> ここでアプリがクラッシュします。

私は独自の「removeAnnotations:」メソッドを実行してそれらすべてを反復処理してデバッグしましたが、クラッシュしたときに、最初に追加したものよりも 1 つ多くの注釈を削除しようとしていることがわかりました。

ユーザーの位置情報が表示されない場合 (位置情報サービスが有効になっていないか、その他の理由で) 問題は発生しなかったため、上記の手順 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;
}
于 2013-10-05T19:29:13.697 に答える