简体   繁体   English

设置地图视图中心坐标后,将从其超级视图中删除自定义注记视图

[英]Custom annotation view is being removed from its superview after setting map view center coordinate

I'm working on a location-aware application that is using MKMapView with custom callout bubbles implemented as MKAnnotationView subclass. 我正在开发一个位置感知应用程序,它使用MKMapView,并将自定义标注气泡实现为MKAnnotationView子类。 Yesterday I've encountered a subtle bug when custom annotation view is not being shown. 昨天我在没有显示自定义注释视图时遇到了一个微妙的错误。 After investigating this issue a bit, I've come up with following results: 在仔细研究了这个问题之后,我想出了以下结果:

  • this issue manifests itself only if I'm trying to show custom annotation view immediately after zooming with pinch gesture. 只有当我尝试使用捏合手势进行缩放后立即显示自定义注释视图时,此问题才会显现。 So for example if you pinch and then pan the map view everything works fine. 因此,例如,如果你捏,然后平移地图视图一切正常。 Programmatically changing map zoom doesn't cause this issue to appear either 以编程方式更改地图缩放不会导致出现此问题
  • setting breakpoint in didMoveToSuperview in my custom annotation view class reveals the following backtrace: 在我的自定义注释视图类的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:] () 

Here, CalloutMapAnnotationView is my custom annotation view class. 这里,CalloutMapAnnotationView是我的自定义注释视图类。 adjustMapRegionIfNeeded method adjusts map view's center coordinate if annotation is too close to map borders which in turn causes removal of CalloutMapAnnotationView instance from its superview. 如果注释太靠近地图边框, adjustMapRegionIfNeeded方法会调整地图视图的中心坐标,从而导致从其超级视图中删除CalloutMapAnnotationView实例。 Why this is happening and what a workaround may be? 为什么会发生这种情况以及解决方法可能是什么?

Further investigation showed even more strange behavior. 进一步调查显示更奇怪的行为。 I added a bunch of debug NSLogs in adjustMapRegionIfNeeded to print each annotation visibility and came up up with following result: 我在adjustMapRegionIfNeeded添加了一堆调试NSLog来打印每个注释可见性,并adjustMapRegionIfNeeded以下结果:

Normal case (custom annotation is displayed): 正常情况(显示自定义注释):

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 annotation is not displayed: 不显示自定义注释:

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

Despite parent annotation and custom callout annotation having the same location, one of them is visible while the other is not. 尽管父注释和自定义标注注释具有相同的位置,但其中一个是可见的,而另一个则不可见。 I'm testing annotation visibility with the following code: 我正在使用以下代码测试注释可见性:

[[self.mapView annotationsInMapRect:self.mapView.visibleMapRect] containsObject:self.annotation]

More than that, the following assertion fails : 更重要的是,以下断言失败

MKMapRect visibleMapRect = self.mapView.visibleMapRect;
MKMapPoint annotationPoint = MKMapPointForCoordinate(self.annotation.coordinate);
NSAssert(MKMapRectContainsPoint(visibleMapRect, annotationPoint) == [[self.mapView annotationsInMapRect:visibleMapRect] containsObject:self.annotation], @"?!");

I've come across the same problem (and most probably used the same tutorial that you did). 我遇到了同样的问题(并且很可能使用了与你相同的教程)。

I've put some NSLogs into the CalloutAnnotationView 's didMoveToSuperView and found that after adding the CalloutAnnotationView , its superview, an instance of MKAnnotationContainerView , is being released. 我将一些NSLog放入CalloutAnnotationViewdidMoveToSuperView ,发现添加CalloutAnnotationView ,它的CalloutAnnotationView (一个MKAnnotationContainerView实例)正在发布。 This could mean that the MKMapView internally recreates its MKAnnotationContainerView when zooming in or out. 这可能意味着MKMapView在放大或缩小时会在内部重新创建其MKAnnotationContainerView

What I did was to do some checking a little bit after adding it: 我做的是在添加后做一些检查:

[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];
  ...
}

It's pretty hacky, yes. 这是非常hacky,是的。 If you find a better solution, please do post. 如果您找到更好的解决方案,请发布。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM