Как добавить прослушиватель кликов к выбранному mkannotationview? - PullRequest
0 голосов
/ 31 марта 2019

Мне нужно нажать на аннотацию на карте. Я могу видеть выбранный вид аннотации вот так mkannotationview

Я хочу добавить прослушиватель щелчков в этом выбранном представлении аннотации, чтобы открыть другой контроллер представления с подробностями аннотации. Как я могу это сделать?

func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
    if let selected = (view.annotation as? CustomAnnotation) {
        self.selectedAnnotation = selected
    }
}

1010 * Отредактированный *

1 Ответ

1 голос
/ 31 марта 2019

Как правило, вы добавляете, например, rightCalloutAccessoryView, а затем внедряете calloutAccessoryControlTapped, как показано в , как сделать выноску с аннотацией с помощью пин-кода?

Но вы говорите:

Мне нужно сделать весь выносной элемент интерактивным

В MapKit нет метода делегата для захвата нажатий на выноску, только на дополнительные представления.Но вы можете добавить свой собственный делегат, чтобы сделать это для вас.

protocol CustomAnnotationViewDelegate: class {
    func didTapCallout(for annotation: MKAnnotation)
}

class CustomAnnotationView: MKPinAnnotationView {
    static let preferredReuseIdentifier = Bundle.main.bundleIdentifier! + ".customAnnotationView"

    weak var delegate: CustomAnnotationViewDelegate?

    override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
        super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)

        canShowCallout = true

        let tap = UITapGestureRecognizer(target: self, action: #selector(didTapAnnotationView(_:)))
        self.addGestureRecognizer(tap)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    @objc func didTapAnnotationView(_ gesture: UITapGestureRecognizer) {
        let location = gesture.location(in: self)

        // ignore taps on the annotation view, itself

        if bounds.contains(location) { return }

        // if we got here, we must have tapped on the callout

        delegate?.didTapCallout(for: annotation!)
    }
}

Затем в iOS 11 и более поздних версиях вы можете зарегистрировать этот reuseIdentifier:

override func viewDidLoad() {
    super.viewDidLoad()

    mapView.register(CustomAnnotationView.self,
                     forAnnotationViewWithReuseIdentifier: CustomAnnotationView.preferredReuseIdentifier)
}

И ваш viewFor может указать делегата:

extension ViewController: MKMapViewDelegate {
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        if annotation is MKUserLocation { return nil }

        let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier, for: annotation) as! CustomAnnotationView
        annotationView.delegate = self
        return annotationView
    }
}

Или, если вам нужно поддерживать версии iOS до 11, вы не зарегистрируете идентификатор повторного использования, но вам придется вручную создавать экземпляр CustomAnnotationView, если он не был успешно удален из очереди:

extension ViewController: MKMapViewDelegate {
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        if annotation is MKUserLocation { return nil }

        var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: CustomAnnotationView.preferredReuseIdentifier) as? CustomAnnotationView
        if annotationView == nil {
            annotationView = CustomAnnotationView(annotation: annotation, reuseIdentifier: CustomAnnotationView.preferredReuseIdentifier)
            annotationView?.delegate = self
        } else {
            annotationView?.annotation = annotation
        }

        return annotationView
    }
}

В любом случаеТеперь вы можете настроить контроллер представления на новый CustomAnnotationViewDelegate:

extension ViewController: CustomAnnotationViewDelegate {
    func didTapCallout(for annotation: MKAnnotation) {
        print("tapped callout for \(annotation)")
    }
}

Но обратите внимание, что в приведенном выше описании я добавляю распознаватель жестов касания в методе CustomAnnotationView init,чтобы гарантировать, что жест касания создается один и только один раз, когда представление аннотации создается впервые.

...