【问题标题】:Custom annotation view is being removed from its superview after setting map view center coordinate设置地图视图中心坐标后,自定义注释视图正在从其超级视图中删除
【发布时间】:2011-10-15 01:45:10
【问题描述】:

我正在开发一个位置感知应用程序,该应用程序使用 MKMapView 和作为 MKAnnotationView 子类实现的自定义标注气泡。昨天,当自定义注释视图未显示时,我遇到了一个微妙的错误。在调查了这个问题之后,我得出了以下结果:

  • 仅当我尝试在使用捏合手势缩放后立即显示自定义注释视图时,才会出现此问题。因此,例如,如果您捏然后平移地图视图,一切正常。以编程方式更改地图缩放也不会导致出现此问题
  • 在我的自定义注释视图类中的 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 实例从其父视图中移除。为什么会发生这种情况以及可能的解决方法是什么?

进一步调查显示出更奇怪的行为。我在adjustMapRegionIfNeeded 中添加了一堆调试 NSLogs 来打印每个注释可见性并得出以下结果:

正常情况(显示自定义注解):

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], @"?!");

【问题讨论】:

    标签: iphone ios mapkit mkannotation mkannotationview


    【解决方案1】:

    我遇到了同样的问题(很可能使用了与您相同的教程)。

    我在CalloutAnnotationViewdidMoveToSuperView中放了一些NSLogs,发现添加CalloutAnnotationView之后,它的superview,MKAnnotationContainerView的一个实例,正在被释放。这可能意味着MKMapView 在放大或缩小时会在内部重新创建其MKAnnotationContainerView

    我所做的是在添加后做一些检查:

    [self.mapView addAnnotation: m_calloutAnnotation];
    [self performSelector: @selector(checkCalloutAnnotationVisibility)
               withObject: nil
               afterDelay: 0.15];
    ...
    
    - (void) checkCalloutAnnotationVisibility
    {
      if (!m_calloutAnnotationView.window)
      {
        [self.mapView removeAnnotation: m_calloutAnnotation];
        [self.mapView addAnnotation: m_calloutAnnotation];
    
        [self performSelector: @selector(checkCalloutAnnotationVisibility)
                   withObject: nil
                   afterDelay: 0.1];
      }
    }
    
    ...
    
    - (void)          mapView: (MKMapView *)        mapView
    didDeselectAnnotationView: (MKAnnotationView *) view
    {
      [NSObject cancelPreviousPerformRequestsWithTarget: self
                                               selector:
                                         @selector(checkCalloutAnnotationVisibility)
                                                 object: nil];
      ...
    }
    

    这很 hacky,是的。如果您找到更好的解决方案,请发布。 :)

    【讨论】:

    • 嗯,我已经设法通过将区域调整代码移动到 mapView:didAddAnnotationViews: 来解决这个问题,这似乎为我解决了问题。
    • 现在这是一种更优雅的解决方法。好的。现在摆脱快速修复...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-23
    相关资源
    最近更新 更多