MKAnnotationView サブクラスとして実装されたカスタム コールアウト バブルで MKMapView を使用している位置認識アプリケーションに取り組んでいます。昨日、カスタム注釈ビューが表示されていないときに微妙なバグに遭遇しました。この問題を少し調べたところ、次の結果が得られました。
- この問題は、ピンチ ジェスチャでズームした直後にカスタム注釈ビューを表示しようとした場合にのみ現れます。たとえば、マップ ビューをピンチしてからパンすると、すべて正常に動作します。プログラムでマップのズームを変更しても、この問題は発生しません
カスタム アノテーション ビュー クラスの didMoveToSuperview にブレークポイントを設定すると、次のバックトレースが表示されます。
#0 -[CalloutMapAnnotationView didMoveToSuperview] #1 0x00186857 in -[UIView(Hierarchy) removeFromSuperview] () #2 0x00e14c70 in -[MKAnnotationContainerView _removeAnnotationView:updateCollections:] () #3 0x00e196cb in -[MKAnnotationContainerView _removeAnnotationViews:] () #4 0x00e19f51 in -[MKAnnotationContainerView _displayAnnotationsInMapRect:includePending:animated:removeOffscreenAnnotations:] () #5 0x00e1aaa7 in -[MKAnnotationContainerView _refreshDisplayedAnnotations] () #6 0x00dfc508 in -[MKMapView _didChangeRegionMidstream:centerPoint:] () #7 0x00e0165c in -[MKMapView _goToCenterCoordinate:zoomLevel:animationType:] () #8 0x00df34c3 in -[MKMapView goToCenterCoordinate:zoomLevel:animationType:] () #9 0x00e0086f in -[MKMapView setCenterCoordinate:animated:] () #10 0x00036fc3 in -[CalloutMapAnnotationView adjustMapRegionIfNeeded] #11 0x00037c63 in -[CalloutMapAnnotationView didMoveToSuperview] #12 0x0017f750 in -[UIView(Internal) _addSubview:positioned:relativeTo:] () #13 0x0017dc00 in -[UIView(Hierarchy) insertSubview:atIndex:] () #14 0x00e2049f in -[MKAnnotationContainerView _addViewForAnnotation:] () #15 0x00e199a5 in -[MKAnnotationContainerView _addViewsForAnnotations:animated:] () #16 0x00e19f0d in -[MKAnnotationContainerView _displayAnnotationsInMapRect:includePending:animated:removeOffscreenAnnotations:] () #17 0x00e1a9e2 in -[MKAnnotationContainerView showAddedAnnotationsAnimated:] ()
ここで、CalloutMapAnnotationView はカスタム アノテーション ビュー クラスです。adjustMapRegionIfNeeded
メソッドは、注釈がマップの境界線に近すぎる場合にマップ ビューの中心座標を調整します。これにより、そのスーパービューから CalloutMapAnnotationView インスタンスが削除されます。これが発生する理由と回避策を教えてください。
さらに調査すると、さらに奇妙な動作が示されました。各注釈の可視性を出力するために一連のデバッグ NSLog を追加しadjustMapRegionIfNeeded
たところ、次の結果が得られました。
通常の場合 (カスタム アノテーションが表示されます):
Custom callout annotation location: (55.821350, 37.497490)
Parent annotation location: (55.821350, 37.497490)
Custom callout annotation visibility before adjustment: 1
Custom callout annotation visibility after adjustment: 1
Parent annotation visibility: 1
カスタム注釈は表示されません:
Custom callout annotation location: (55.821350, 37.497490)
Parent annotation location: (55.821350, 37.497490)
Custom callout annotation visibility before adjustment: 1
Custom callout annotation visibility after adjustment: 0
Parent annotation visibility: 1
親アノテーションとカスタム コールアウト アノテーションの位置は同じですが、一方は表示され、もう一方は表示されません。次のコードで注釈の可視性をテストしています。
[[self.mapView annotationsInMapRect:self.mapView.visibleMapRect] containsObject:self.annotation]
それ以上に、次のアサーションは失敗します。
MKMapRect visibleMapRect = self.mapView.visibleMapRect;
MKMapPoint annotationPoint = MKMapPointForCoordinate(self.annotation.coordinate);
NSAssert(MKMapRectContainsPoint(visibleMapRect, annotationPoint) == [[self.mapView annotationsInMapRect:visibleMapRect] containsObject:self.annotation], @"?!");