Search code examples
iosswiftannotationsmapkit

How do I add button to MKPointAnnotation in Swift


I want to add a button that is going to appear on the right of the annotation when a user tapped on a marker. Here's currently what I'm doing.

  1. Download a json file from my website.
  2. Open the file and parse it.
  3. Plot all the markers using coords from the json file
  4. But now..how do I add a button to the right of my annotation that will move to a detailViewController when a user tap it?

here's my ViewDidLoad

//Retrieve the existing JSON from document directory
        let defaults = UserDefaults.standard
        let fileUrl = defaults.url(forKey: "pathForJSON")
        do {
            let jsonData = try Data(contentsOf: fileUrl!, options: [])
            let myJson = try JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers) as! [Dictionary<String,AnyObject>]
            // print out the content
//            print("My JSON: ", myJson)
            createAnnotation(locations: myJson)
        } catch {
            print(error)
        }

My createAnnotation function.

func createAnnotation(locations: [Dictionary<String, AnyObject>]) {
        for location in locations {
            let annotation = MKPointAnnotation()
            annotation.title = location["name"] as? String
            let lat = (location["latitude"] as! NSString).doubleValue
            let lon = (location["longitude"] as! NSString).doubleValue
            annotation.coordinate = CLLocationCoordinate2D(latitude: lat, longitude: lon)
            mapView.addAnnotation(annotation)
//            print(annotation)
        }
    }

Solution

  • Try the following code

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        if annotation is MKUserLocation {
            return nil
        }
    
        let reuseId = "pin"
        var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
        if pinView == nil {
            pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
            pinView?.canShowCallout = true
    
            let rightButton: AnyObject! = UIButton(type: UIButton.ButtonType.detailDisclosure)
            pinView?.rightCalloutAccessoryView = rightButton as? UIView
        }
        else {
            pinView?.annotation = annotation
        }
    
        return pinView
    }
    

    Don't forget to set mapView's delegate

    mapView.delegate = self