Satsuki
Satsuki

Reputation: 2196

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!

Upvotes: 0

Views: 1081

Answers (3)

Cristik
Cristik

Reputation: 32779

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.

Upvotes: 1

Satsuki
Satsuki

Reputation: 2196

   func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
        var index = shops.index(of: view.annotation! as! ShopLocation)!
    }

Did the job for me.

Upvotes: 1

Kosuke Ogawa
Kosuke Ogawa

Reputation: 7451

Try the following code:

func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
    guard let annotation = view.annotation else {
        return
    }
    for (index, item) in LocationList().shop.enumerated() {
        if let title = view.annotation?.title {
            if item.name! == title! {
                print(index)
                break
            }
        }
    }

Upvotes: 1

Related Questions