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
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
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