Пользовательский вид аннотации удаляется из своего супервизора после установки координаты центра вида карты.

Я работаю над приложением с учетом местоположения, которое использует 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 из его супервизора. Почему это происходит и что можно сделать?

Дальнейшее расследование показало еще более странное поведение. Я добавил кучу отладочных журналов NSLogs в 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], @"?!");

person Andrey Mishanin    schedule 28.07.2011    source источник


Ответы (1)


Я столкнулся с той же проблемой (и, скорее всего, использовал тот же учебник, что и вы).

Я поместил несколько журналов NSLog в CalloutAnnotationView didMoveToSuperView и обнаружил, что после добавления CalloutAnnotationView его супервизор, экземпляр 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];
  ...
}

Да, это довольно взломано. Если вы найдете лучшее решение, напишите, пожалуйста. :)

person Kenn Cal    schedule 22.08.2011
comment
Что ж, мне удалось решить эту проблему, переместив код настройки региона в mapView:didAddAnnotationViews:, и это, кажется, исправляет ситуацию для меня. - person Andrey Mishanin; 22.08.2011
comment
Это более элегантный способ решения. Хороший. Теперь, чтобы избавиться от быстрого исправления ... - person Kenn Cal; 23.08.2011