# 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](https://developer.apple.com/documentation/mapkit/mkannotation) 

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’écran 2021-04-18 à 19.17.40.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1618766302269/b0k2HJXp4.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’écran 2021-04-18 à 19.27.37.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1618766882836/2ag1GDQT0.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

