5

I've just got stuck trying to add a detail button to my annotation point, unfortunately I don't know how to do it. Does anyone could help me with that?

The image below presents what I'd like to achieve. Thanks! enter image description here

MapKitViewController:

import UIKit
import MapKit
import CoreLocation

class MapKitViewController: UIViewController, MKMapViewDelegate
{

let locationManager = CLLocationManager()

@IBOutlet weak var nmapView: MKMapView!
override func viewDidLoad()
{
    super.viewDidLoad()
    locationManager.requestWhenInUseAuthorization()
    locationManager.startUpdatingLocation()
    let location = CLLocationCoordinate2D(
        latitude: 53.4265107,
        longitude: 14.5520357)

    let span = MKCoordinateSpanMake(0.05, 0.05)
    let region = MKCoordinateRegion(center: location, span: span)
    nmapView.setRegion(region, animated: true)
    nmapView.showsPointsOfInterest = false
    nmapView.showsUserLocation = true
    displayMarkers()
}

func displayMarkers() -> Void
{
    let jsonURL: NSURL = NSURL(string: "http://jsonstring.com/")!

    var dataFromNetwork: NSData = NSData(contentsOfURL: jsonURL)!
    let json = JSON(data: dataFromNetwork)
    var jsonSize = json.count

    var todaysDate:NSDate = NSDate()
    var dateFormatter:NSDateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd"
    var formattedDate:String = dateFormatter.stringFromDate(todaysDate)

    let annotationView = MKAnnotationView()
    let detailButton: UIButton = UIButton.buttonWithType(UIButtonType.DetailDisclosure) as UIButton
    annotationView.rightCalloutAccessoryView = detailButton


    for(var i = 0; i < jsonSize; i++)
    {
        if(json[i]["rozpoczecie"].stringValue == formattedDate)
        {
            let clubID = json[i]["id_klub"].stringValue
            let annotation = MKPointAnnotation()
            let (resultSet, err) = SD.executeQuery("SELECT * FROM Clubs WHERE ID = ?", withArgs: [clubID])
            if(err != nil){println("blad")}
            else
            {
                for row in resultSet
                {
                    let name = row["Name"]?.asString()
                    let latitude = row["Latitude"]?.asDouble()
                    let longitude = row["Longitude"]?.asDouble()
                    annotation.title = name
                    var markerLatitude: Double = latitude!
                    var markerLongitude: Double = longitude!
                    let location = CLLocationCoordinate2D(latitude: markerLatitude, longitude: markerLongitude)
                    annotation.setCoordinate(location)
                    annotation.subtitle = json[i]["nazwa"].stringValue
                }
                nmapView.addAnnotation(annotation)
            }
        }
    }
}
wtznc
  • 895
  • 2
  • 14
  • 26

1 Answers1

12

You are doing it right.You just need to have these methods implemented for adding button along with title and subtitle

iOS 8 and Xcode 6

 import UIKit
 import MapKit
 import CoreLocation

 class MapKitViewController: UIViewController, MKMapViewDelegate
 {
    let locationManager = CLLocationManager()
    @IBOutlet weak var nmapView: MKMapView!
    override func viewDidLoad()
    {
        super.viewDidLoad()
        locationManager.requestWhenInUseAuthorization()
        locationManager.startUpdatingLocation()
        let location = CLLocationCoordinate2D(
            latitude: 53.4265107,
            longitude: 14.5520357)

        let span = MKCoordinateSpanMake(0.05, 0.05)
        let region = MKCoordinateRegion(center: location, span: span)
        nmapView.setRegion(region, animated: true)
        nmapView.showsPointsOfInterest = false
        nmapView.showsUserLocation = true
        displayMarkers()
    }

    // When user taps on the disclosure button you can perform a segue to navigate to another view controller
    func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!, calloutAccessoryControlTapped control: UIControl!) {
        if control == view.rightCalloutAccessoryView{
            println(view.annotation.title) // annotation's title
            println(view.annotation.subtitle) // annotation's subttitle

            //Perform a segue here to navigate to another viewcontroller
            // On tapping the disclosure button you will get here
        }
    }

    // Here we add disclosure button inside annotation window
    func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {

        println("viewForannotation")
        if annotation is MKUserLocation {
            //return nil 
            return nil
        }

        let reuseId = "pin"
        var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView

        if pinView == nil {
            //println("Pinview was nil")
            pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
            pinView!.canShowCallout = true
            pinView!.animatesDrop = true
            }

        var button = UIButton.buttonWithType(UIButtonType.DetailDisclosure) as UIButton // button with info sign in it

        pinView?.rightCalloutAccessoryView = button


        return pinView
    }


    func displayMarkers() -> Void
    {
        let jsonURL: NSURL = NSURL(string: "http://atnight.wtznc.com/json.php")!

        var dataFromNetwork: NSData = NSData(contentsOfURL: jsonURL)!
        let json = JSON(data: dataFromNetwork)
        var jsonSize = json.count

        var todaysDate:NSDate = NSDate()
        var dateFormatter:NSDateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd"
        var formattedDate:String = dateFormatter.stringFromDate(todaysDate)

        let annotationView = MKAnnotationView()

        // Adding button here wont do anything  so remove these two lines


        let detailButton: UIButton = UIButton.buttonWithType(UIButtonType.DetailDisclosure) as UIButton
        annotationView.rightCalloutAccessoryView = detailButton

        // For adding button we have to use a method named as viewForAnnotation 

        for(var i = 0; i < jsonSize; i++)
        {
            if(json[i]["rozpoczecie"].stringValue == formattedDate)
            {
                let clubID = json[i]["id_klub"].stringValue
                let annotation = MKPointAnnotation()
                let (resultSet, err) = SD.executeQuery("SELECT * FROM Clubs WHERE ID = ?", withArgs: [clubID])
                if(err != nil){println("blad")}
                else
                {
                    for row in resultSet
                    {
                        let name = row["Name"]?.asString()
                        let latitude = row["Latitude"]?.asDouble()
                        let longitude = row["Longitude"]?.asDouble()
                        annotation.title = name
                        var markerLatitude: Double = latitude!
                        var markerLongitude: Double = longitude!
                        let location = CLLocationCoordinate2D(latitude: markerLatitude, longitude: markerLongitude)
                        annotation.setCoordinate(location)
                        annotation.subtitle = json[i]["nazwa"].stringValue
                    }
                    nmapView.addAnnotation(annotation)
                }
            }
        }
    }
}

Check out my output.

enter image description here

Talha Q
  • 4,350
  • 4
  • 28
  • 40
  • Thanks! I'll try implement your code tomorrow because going to bed right now. – wtznc Jan 29 '15 at 22:54
  • I have added the output.If you still face any troubles feel free to comment. :) – Talha Q Jan 29 '15 at 23:09
  • When using the calloutAccessoryControlTapped delegate method, you don't need to (actually should not) do addTarget and write a custom method (like showDetail). The way it's written, app will call both methods when disclosure is tapped. Also, when view is dequeued, you should update its annotation property (important when you have multiple annotations). –  Jan 30 '15 at 12:33
  • Thanks @Anna i have updated the code.Check it out do point the error if any. – Talha Q Jan 30 '15 at 13:14
  • Could you tell me where should I use method `viewForAnnotation`? Because I have just added functions which you wrote but the button still does not appear. – wtznc Jan 30 '15 at 13:47
  • i have added the full code.Check it out do test it.Remove any extra brackets if i added any.Because i haven't tested it on xcode – Talha Q Jan 30 '15 at 15:20
  • Always love to help...Cheers :) – Talha Q Jan 30 '15 at 19:40
  • 3
    Two suggestions: 1. If you successfully dequeue a previous `MKPinAnnotationView`, don't forget to reset the `annotation` property. As it is, if an `MKPinAnnotationView` is reused, it probably won't be in the right place. 2. The button syntax is now `UIButton(type: .DetailDisclosure)`. – Rob Oct 16 '15 at 17:26
  • this is what i am looking for . do you have this code in objective c ? i mean how to keep disclosure button there in objective c ? – Moxarth Jun 24 '17 at 07:45