Annotation et AnnotationView

Annotation et AnnotationView

Plusieurs points peuvent être indiqués sur une carte, commerces, station de taxi, lieux visités, lieux retenus pour intérêt particulier,....

Ces points comprennent deux caractéristiques :

  • annotation pour associer un objet à un emplacement
  • annotationView pour matérialiser cet objet sur la carte

ANNOTATION

  • MKAnnotation : An interface for associating your content with a specific map location

Pour être représenter sur une carte par une AnnotationView, un objet doit se conformer au protocole MKAnnotation et peut comprendre 3 propriétés :

coordinate: CLLocationCoordinate2D

var title: String? (optionnel)

var subtitle: String? (optionnel)

Les coordonnées (latitude, longitude) sont obligatoires pour pouvoir placer l'objet sur une carte.

Exemple d'une class pour représenter des objets sur une carte

class ObjetPin: NSObject, MKAnnotation {
    let title: String?
    let subtitle: String?
    let coordinate: CLLocationCoordinate2D

    init(title: String?, subtitle: String?, coordinate: CLLocationCoordinate2D) {
        self.title = title
        self.subtitle = subtitle
        self.coordinate = coordinate

        super.init()
    }
}

Et la création des annotations dans une boucle, et leurs ajout sur la carte

let annotation = ObjetPin(title: address, subtitle: state, coordinate: coordinate)

 self.mapView.addAnnotation(annotation)
  • MKPointAnnotation : A string-based annotation that you apply to a specific map point

Annotation simple, peut être utilisée pour la localisation de l'utilisateur par exemple,

let pin = MKPointAnnotation()
        pin.coordinate = center
        pin.title = "I'm Here"
        mapView.addAnnotation(pin)
  • Il y a aussi MKClusterAnnotation : An annotation that groups two or more distinct annotations into a single entity.

Plus de détails sur les annotations dans la documentation Apple

Cette dernière annotation nous rappelle une propriété d'AnnotationView, qui permet dans le cas de zoom sur la carte, de regrouper les annotations proches en une seule, avec un chiffre à l'intérieur de l'AnnotationView, indiquant le nombre d'annotations

annotationView.clusteringIdentifier = ""

ANNOTATIONVIEW

  • MKAnnotationView : The visual representation of one of your annotation objects

Quand des coordonnées d'objet sont présentés à une carte, le "delegate" (MapViewDelegate) est appelé pour indiquer la représentation visuelle de cet objet. Par défaut il y a les épingles Capture d’écran 2021-04-18 à 19.17.40.png Dans la fonction viewFor annotation du protocole, plusieurs propriétés permettent de personnaliser ces vues (.tintColor, .image,...).

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

let annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: "")

annotationView.markerTintColor = .blue
annotationView.canShowCallout = true
...
}

L'utilisation d'un switch permet de personnaliser les vues en fonction de la propriété subtitle par exemple. Cette propriété subtitle pourrait représenté les catégories d'objets.

  • MKMarkerAnnotationView : An annotation view that displays a balloon-shaped marker at the designated location

Hérite de la classe MKAnnotationView, et permet en plus d'afficher un encart bulle quand l'annotationview est "cliquée". Peuvent être afficher le title et subtitle de l'objet.

annotationView.canShowCallout = true

Un bouton peut être ajouter dans l'encart Capture d’écran 2021-04-18 à 19.27.37.png

let button = UIButton(type: .detailDisclosure)
            annotationView.rightCalloutAccessoryView = button

Son action est définit dans une des fonction mapView() du MapViewDelegate

func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {  }

Par exemple, nous pouvons appeler une instance de MapItem pour calculer le parcours de notre position vers ce lieu.

Dans notre modèle d'objet, nous créons une propriété calculée (computed propertie) représentant un MapItem,

import Foundation
import MapKit
import Contacts

class ObjetPin: NSObject, MKAnnotation {
    let title: String?
    let subtitle: String?
    let coordinate: CLLocationCoordinate2D

    init(title: String?, subtitle: String?, coordinate: CLLocationCoordinate2D) {
        self.title = title
        self.subtitle = subtitle
        self.coordinate = coordinate

        super.init()
    }

    var mapItem: MKMapItem? {
        guard let location = title else { return nil }

        let addressDict = [CNPostalAddressStreetKey: location]
        let placemark = MKPlacemark(coordinate: coordinate, addressDictionary: addressDict)
        let mapItem = MKMapItem(placemark: placemark)
        return mapItem
    }
}

Et nous appelons cette propriété dans la fonction calloutAccessoryControlTapped du delegate

func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
        guard let objetPin = view.annotation as? ObjetPin else { return }

        let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving]

        objetPin.mapItem?.openInMaps(launchOptions: launchOptions)  
    }

bon code