iosswiftmapkitmapkitannotation

Get the array index from annotation


Hi I would like to get the index number when the user taps on the annotation. I have the following code..

class ShopLocation: NSObject, MKAnnotation{

 var identifier = "Shop location"
 var title: String?
 var subtitle: String?
 var coordinate: CLLocationCoordinate2D

    init(name:String,lat:CLLocationDegrees,long:CLLocationDegrees,addInfo:String){
        title = name
        coordinate = CLLocationCoordinate2DMake(lat, long)
        subtitle = addInfo
    }

}
    class LocationList: NSObject {


        var shop = [ShopLocation]()

          override init(){
            shop += [ShopLocation(name:"t1", lat:35.673647,long:139.727686,addInfo:"info")]

            shop += [ShopLocation(name:"t2", lat:35.671928,long:139.760815,addInfo:"info")]

            shop += [ShopLocation(name:"t3", lat:35.713232,long:139.793467,addInfo:"info")]
    }

The annotations are displayed on a map. I would like to get the index for example if t1 is tapped I get an index of 1.

I don't know what to write in

func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
    LocationList().shop.index(of: )

}

Thank you!


Solution

  • I assume ShopLocation already conforms to MKAnnotation, if not then make it conform and pass it to MKAnnotationView's initializer. This will make it available in the delegate method, via view.annotation

    Now that you have access to the ShopLocation instance, there are two solutions that come to my mind for finding it's index in the shop

    1. Conform to Equatable - this will enable the firstIndex(of:) method of Array (actually of Collection to which Array conforms)

       extension ShopLocation: Equatable {
           static func ==(lhs: ShopLocation, rhs: ShopLocation) -> Bool {
               // place here the conditions for two instances to be equal
           }
      
       // ... later in the code
      
       func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
           guard let shopLocation = view.annotation as? ShopLocation else {
               // this early returns if the annotation is not a shop location,
               // if you don't wan't that you can use an if-let instead
               return
           }
           let index = LocationList().shop.firstIndex(of: shopLocation)
           // do what you need with the index
       }
      
    2. Use the firstIndex(where:) method of Array (again, actually of Collection :)

       func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
           guard let shopLocation = view.annotation as? ShopLocation else {
               // this early returns if the annotation is not a shop location,
               // if you don't wan't that you can use an if-let instead
               return
           }
           let index = LocationList().shop.firstIndex(where: { shopLocation in
               return // same conditions as for the Equatable
           })
           // do what you need with the index
       }
      

    Personally, I'd recommend approach #1, even Apple recommends conforming value types to Equatable. Conforming to Equatable helps with code reduction, and enables lots of other functions besides the index(of:) mentioned here.