Как определить порядок перекрытия MKAnnotationViews?

голоса
29

У меня есть несколько MKAnnotations (и их соответствующие взгляды) на моей карте, и это иногда становится действительно переполнен. Теперь, аннотации в моем приложении в двух вариантах: некоторые из них связаны оставаться там, где они есть, в то время как другие будут двигаться, как время идет. Я предпочел бы иметь более стабильные визуально в фоновом режиме и движущиеся из них всегда проходят перед ними.

Можно было бы подумать, возможно, что аннотации совсем недавно добавленные к карте будет в конечном итоге на фронт (или, альтернативно, в самом конце, по крайней мере), но это только кажется, не является правилом. Насколько я могу сказать, я создаю и добавить все неподвижные аннотации, а затем добавить некоторые вновь инстанцировано двигающиеся аннотации, но многие из них (хотя и не все!) В конечном итоге обращается под постоянно вкопанными из них.

Интересно, что, когда проходит время, и все же новые подвижные аннотаций создаются, они, как правило, тяготеют больше к вершине, чем первые из них - даже если все движущиеся объекты аннотирования были созданы только после того, как неподвижные части уже были добавлены на карту.

Кто-нибудь знает трюк, чтобы изменить этот странный естественный порядок взглядов аннотаций на карте? Я пытался искать Map Kit API, но это, кажется, не говоря уже о таких вещах.

Задан 17/07/2009 в 20:33
источник пользователем
На других языках...                            


7 ответов

голоса
38

Итак, для метода использования раствора от MKMapViewDelegate


- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views
 

В этом методе вы должны изменить AnnotationView после того, как был добавлен в MapKit View. Таким образом, код может, выглядит следующим образом:


- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
   for (MKAnnotationView * annView in views) {
      TopBottomAnnotation * ann = (TopBottomAnnotation *) [annView annotation];
      if ([ann top]) {
         [[annView superview] bringSubviewToFront:annView];
      } else {
         [[annView superview] sendSubviewToBack:annView];
      }
   }

}

Это работает для меня.

Ответил 31/07/2009 в 17:09
источник пользователем

голоса
11

Попробуйте zPosition установки пояснительных слоя (annotationView.layer.zPosition) в:

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views;
Ответил 03/05/2013 в 11:40
источник пользователем

голоса
4

Swift 3:

Я получаю расположение выводов из API, и я имел аналогичные вопросы, булавки, которые должны были быть на вершине не были. Я был в состоянии решить, как это.

var count = 0 // just so we don't get the same index in bottom pins
func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {  
    for view in views {
        view.layer.zPosition = CGFloat(count)
    }
    count += 1
    if count > 500 {
        count = 250 // just so we don't end up with 999999999999+ as a value for count, plus I have at least 30 pins that show at the same time and need to have lower Z-Index values than the top pins. 
    }

}

Надеюсь это поможет

Ответил 05/12/2016 в 21:06
источник пользователем

голоса
3

Под прошивкой 11, реализация displayPriorityнарушил все решения , которые используют bringSubviewToFrontили zPosition.

Если переопределить CALayer в пояснительных, вы можете бороться контроль zPosition назад от ОС.

class AnnotationView: MKAnnotationView {

    /// Override the layer factory for this class to return a custom CALayer class
    override class var layerClass: AnyClass {
        return ZPositionableLayer.self
    }

    /// convenience accessor for setting zPosition
    var stickyZPosition: CGFloat {
        get {
            return (self.layer as! ZPositionableLayer).stickyZPosition
        }
        set {
            (self.layer as! ZPositionableLayer).stickyZPosition = newValue
        }
    }

    /// force the pin to the front of the z-ordering in the map view
   func bringViewToFront() {
        superview?.bringSubview(toFront: self)
        stickyZPosition = CGFloat(1)
    }

    /// force the pin to the back of the z-ordering in the map view
   func setViewToDefaultZOrder() {
        stickyZPosition = CGFloat(0)
    }

}

/// iOS 11 automagically manages the CALayer zPosition, which breaks manual z-ordering.
/// This subclass just throws away any values which the OS sets for zPosition, and provides
/// a specialized accessor for setting the zPosition
private class ZPositionableLayer: CALayer {

    /// no-op accessor for setting the zPosition
    override var zPosition: CGFloat {
        get {
            return super.zPosition
        }
        set {
            // do nothing
        }
    }

    /// specialized accessor for setting the zPosition
    var stickyZPosition: CGFloat {
        get {
            return super.zPosition
        }
        set {
            super.zPosition = newValue
        }
    }
}
Ответил 25/01/2018 в 23:23
источник пользователем

голоса
2

Я нахожу , что это изменение порядка взглядов аннотаций вызывает выноска , что всплывает , когда один щелкает больше не быть на вершине всех аннотаций. Я даже пытался ее переработки , так что вместо того , bringSubviewToFrontи sendSubviewToBackя использую , insertSubview:aboveSubviewи insertSubview:belowSubview:где второй аргумент является первой annotationView в списке. Это , казалось бы вызвать гораздо меньше спереди назад рассеяние, но выходы вызова еще всплывали в некоторых аннотациях.

Ответил 05/11/2009 в 15:21
источник пользователем

голоса
1

В функции делегата, вы можете выбрать булавку, чтобы заставить его на вершине:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?` {
    ...
    if my annotation is the special one {
        annotationView.isSelected = true
    }
    ...
}
Ответил 18/02/2019 в 01:32
источник пользователем

голоса
0

Я на самом деле нужно, чтобы сделать это, и ни один из (текущих) ответов, казалось, обеспечить надежную реализацию. Они сортируют работали, но панорамирование карты, выбрав аннотации, или масштабирование может испортить заказ снова.

Окончательное, хорошо себя решение было не так тривиально, поэтому я просто наметить шаги , которые я сделал здесь. Упорядочение аннотации , которая MKMapViewиспользует не уважает добавляемый порядок или даже порядок переопределенной annotationsсобственности. Так...


меры

• Создайте CADisplayLink
• Каждый кадр, изменить порядок аннотаций с использованием как на zPosition слоя и упорядочивание вида по в SuperView в subviewsмассиве.
• Если выбран вид, продвигать его на фронт в вашей схеме заказа
• Нажатие на аннотациях еще уважает внутреннюю MKMapViewупорядоченность, несмотря на уже сделанные изменения. Чтобы противостоять этому, добавьте MKMapViewDelegate
• В объекте делегата mapView:didSelect:метод, проверьте , если выбранная аннотация то , что вы хотели бы , чтобы это были
• Вы можете выяснить , правильную / приоритетную аннотацию, выполнив хит тестов на аннотациях себя, со своей собственной упорядоченностью приняты во внимание
• Если выбранный аннотаций является правильным, отлично. Если нет, то вручную выбрать правильную аннотацию , используяselectAnnotation:animated:


И там у вас есть. Описанный выше метод, кажется, работает хорошо, и падение производительности при выполнении этого каждого кадра не так уж плохо. Вы также можете посмотреть на переключение на MapBox, который я считаю, поддерживает порядок аннотаций, но это не всегда возможно по разным причинам.

Ответил 15/09/2017 в 01:54
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more