Custom Annotation

Les annotations ont trois propriétés, "title", "subtitle" et "coordinate".

Ces propriétés permettent d'afficher des informations, notamment dans le callout, cette bulle qui se place au dessus de l'annotationView.

Dernièrement je voulais afficher dans une autre vue, les informations détaillées d'un objet, à partir du bouton information i du callout.

Avec la fonction calloutAccessoryControlTapped du MapViewDelegate, je ne pouvais passer que les données contenues dans title, subtitle et coordinate.

J'ai créé une classe pour personnaliser une annotation, puis caster les annotations.

CUSTOM ANNOTATION

Pour créer une annotation personnalisée, créer une nouvelle classe qui hérite des protocoles NSObject et MKAnnotation et ajouter un initialisateur.

class ObjetAnnotation: NSObject, MKAnnotation {
    let title: String?
    let subtitle: String?
    let coordinate: CLLocationCoordinate2D
    let url: String?
    let adresse: String?
    let horaire: String?
    let tel: String?

    init(title: String?, subtitle: String?, coordinate: CLLocationCoordinate2D, url: String?, adresse: String?, horaire: String?, tel: String?) {
        self.title = title
        self.subtitle = subtitle
        self.coordinate = coordinate
        self.url = url
        self.adresse = adresse
        self.horaire = horaire
        self.tel = tel

        super.init()
    }

Dans cette classe, nous ajouter aux trois propriétés de bases, autant de propriétés dont nous avons besoin.

CREATION D'ANNOTATION PERSONNALISEE

Nous pouvons créer une annotation customisée

let annotation = ObjetAnnotation(title: title, subtitle: adresse, coordinate: coordinate, url: url, adresse: address, horaire: horaire, tel: tel)

self.mapView.addAnnotation(annotation)

Même pour l'utilisateur

let userAnnotation = ObjetAnnotation(title: KEY_ME, subtitle: "I'm Here 😉", coordinate: center, url: "", adresse: "", horaire: "", tel: "")

mapView.addAnnotation(userAnnotation)

Dans le callout n'apparaîtront que le title et subtitle. Mais il est possible d'ajouter une snapShotView dans le callout. Voir le post Stack Overflow

Customize MKAnnotation Callout View?

CASTER les ANNOTATIONS

Maintenant nous pouvons utiliser ce nouveau modèle d'annotation, au même titre que les autres, en apportant la précision lors de l'initialisation de l'annotation dans la méthodes viewFor annotation: MKAnnotation du MKMapViewDelegate

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {

        let annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: "")
        if let annotation = annotation as? ObjetAnnotation {

            annotation.title = .....
            annotation.adresse = .....
            annotation.url = .....

PASSER un OBJET

Maintenant avec notre annotation, nous pouvons passer beaucoup plus d'informations.

Quand nous appuyons sur le bouton information du callout, nous pouvons afficher dans une autre vue toutes les informations de notre objet, comme dans l'exemple suivant, qui push un TableViewController.

func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
        let objet = view.annotation as? ObjetAnnotation

        let infoTVC = self.storyboard?.instantiateViewController(identifier: "InfoTVC") as! InfoTVController
        infoTVC.selectedObjet = objet
        self.navigationController?.pushViewController(infoTVC, animated: true)   
    }

Dans ce TableViewController, nous pouvons récupérer l'url pour afficher une page internet dans une webView

let url = selectedObjet?.url

Et affecter les données de l'objet dans des cellules

cell.textLabel?.text = selectedObjet?.title
cell.detailTextLabel?.text = selectedObjet?.adresse