Add annotations and Polyline to MapView in Swift

In this article, we will see the instructions for adding annotation to MapView, Draw Polylines and Zoom to a region in Swift. Let us see this by adding stations to a Map for Chennai subrban trains and connect these stations using Map Overlay.

Project Setup

 

Create a new project by selecting Single View Application as the project template.

Enter the required information such project name, organization identifier etc.. as shown in the below screenshot. Then save the project in your desired location.

Add MapKit View

 

Navigate to Project navigator and select Main.storyboard file.

We are not using the Auto Layout for this demo, hence disable Use Auto Layout and disable size classes using the options available as part of the File Inspector

Drag and drop MapKit View from object library to the View Controller and make sure to resize the MapView to full view. Add IBOutlet in the ViewController for the MapKit and connect it to the MapKit View in the Interface builder. Also add import MapKit to include MapKit framework for your project.

[code language=”swift”]@IBOutlet weak var mapView: MKMapView!
[/code]

Now if you do a build and run the project in iPhone 6 simulator, you should see the following on simulator.

Zoom to specified region

 

Add the follwing piece of code in ViewController.swift file. And call this function from ViewController’s viewDidLoad function.

[code language=”swift”]//MARK:- Zoom to region

func zoomToRegion() {

let location = CLLocationCoordinate2D(latitude: 13.03297, longitude: 80.26518)

let region = MKCoordinateRegionMakeWithDistance(location, 5000.0, 7000.0)

mapView.setRegion(region, animated: true)
}
[/code]

 

CLLocationCoordinate2D is created by specifying latitude and longitude of the zoom location. Then using MKCoordinateRegionMakeWithDistance set the distance around the speicifed location. Then this region will set as the region for the MapView. Build and run the project should show Map zooming to the speicifed region as shown below.

 

Add plist file to project.

 

All the station details such as title, latitude and longitude are stored in a plist file. You can download the plist from gitHub. Right click on the Project folder (Project navigator) and select “Add Files to <Project name>” option. And select Copy items if needed option while adding the file.

The sample data structure of the plist file is shown below

 

Add place holder class Station

Create a new model class for holding the station data. This class should conform to MKAnnotation and NSObject protocol.

[code language=”swift”]import MapKit

class Station: NSObject, MKAnnotation {
var title: String?
var subtitle: String?
var latitude: Double
var longitude:Double

var coordinate: CLLocationCoordinate2D {
return CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
}

init(latitude: Double, longitude: Double) {
self.latitude = latitude
self.longitude = longitude
}
}[/code]

 

This class has properties for title, subtitle, latitude, longitude and coordinate. Any mappoint should have coordinate for the adding it to the map. This property is mandatory and it is defined in MKAnnotation protocol. The initializer in the class accepts the latitide and longitude details as they are needed for creating the coordinates.

Add annotation to MapKit

We need to iterate through the plist file and create annotation for each stations. Add the following function to ViewController.swift which does the same.

[code language=”swift”]//MARK:- Annotations

func getMapAnnotations() -&gt; [Station] {
var annotations:Array = [Station]()

//load plist file
var stations: NSArray?
if let path = NSBundle.mainBundle().pathForResource("stations", ofType: "plist") {
stations = NSArray(contentsOfFile: path)
}

//iterate and create annotations
if let items = stations {
for item in items {
let lat = item.valueForKey("lat") as! Double
let long = item.valueForKey("long")as! Double
let annotation = Station(latitude: lat, longitude: long)
annotation.title = item.valueForKey("title") as? String
annotations.append(annotation)
}
}

return annotations
}
[/code]

Add the following piece of code in viewDidLoad function.

[code language=”swift”]let annotations = getMapAnnotations()
// Add mappoints to Map
mapView.addAnnotations(annotations)[/code]

Now if you build and run the project, you should see the map with annotations. And on tapping any mappoint should display the title for that station.

Add Polyline to MapView

In order add Polyline overlay to map, we need to implement function defined in MKMapViewDelegate protocol. Add MkMapViewDelegate in the class declaration after UIViewController.

[code language=”swift”]class ViewController: UIViewController, MKMapViewDelegate {[/code]

Then make sure to set the delegate property of the mapview to self so that the ViewController can implement and handle the MKMapViewDelegate functions. Add the following piece of code in viewDidLoad function after the annotations.

[code language=”swift”]
mapView.delegate = self
// Connect all the mappoints using Poly line.

var points: [CLLocationCoordinate2D] = [CLLocationCoordinate2D]()

for annotation in annotations {
points.append(annotation.coordinate)
}
var polyline = MKPolyline(coordinates: &amp;points, count: points.count)
mapView.addOverlay(polyline)
[/code]

create a array of CLLocationCoordinate2D by iterating through annotations. Then create an instance of MKPolyline class by passing array of CLLocationCoordinate2D and count of coordinates. Finally add this polyline to mapView overlay.

Implement the rendererForOverlay MKMapViewDelegate function and return an insatnce of MKPolylineRenderer class

[code language=”swift”]
//MARK:- MapViewDelegate methods

func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -&gt; MKOverlayRenderer! {
if overlay is MKPolyline {
var polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.strokeColor = UIColor.blueColor()
polylineRenderer.lineWidth = 5
return polylineRenderer
}

return nil
}
[/code]

 

Now build and run the app should display the Polyline on the Map.

Download the source code from here


Comments

21 responses to “Add annotations and Polyline to MapView in Swift”

  1. […] – Click here for the updated article in […]

  2. Vineeth Vijayn Avatar
    Vineeth Vijayn

    Thanks a great post!!!

    Will it be possible to move an annotation between 2 points?

    Like if I give a start point and end point an annotation should move repeatedly between those 2 points,

    Will it be possible?

      1. Vineeth Vijayn Avatar
        Vineeth Vijayn

        cannot find setcoordinate function

  3. Thank you wonderful article but I see a couple raw html symbols marring the examples you might want to clear up. (&amp and &-gt;) for example.

  4. I get an warning in the rendererForOverlay method because of the force unwraps. Just wondering if there’s something I can do to fix this.

    1. It is fixed now, can you please try the latest source.

  5. ya it is very nice..
    i want to set a buttons in each and every annotation pins{title,subtitle and button}.
    as it is possible

  6. I’m sorry, I’m new to development but what is plist and where can I find this plist from github.

  7. func getMapAnnotations() -> [Station] {

    i am not able to understand ” ->” and xcode is also showing error on this line.

    1. It means it is a return parameter, please try to replace with hyphen and greater than sign ->

  8. Hi, thanx for the great tutorial.

    I understand the code but am have trouble trying to do the same thing when a navigator bar button item was pressed.

    I placed the code of viewdidLoad from
    // Connect all the mappoints using Poly line. and later
    to the button’s action section without forgetting to
    call getMapAnnotations().
    But when I tap the button the app fails and shows a EXC_BAD.

    Besides that I am trying to erase the annotation pins by a different navigation bar button item. It does not work too.

    Could you be kind enough to give me a advice?

  9. How would i change the code so it does not show all the pins but a user can enter the title in a search box and then the map would show the pin. I feel I am close but am going crazy trying to add this. Please help 🙂 Thanks

  10. Hello, thank you for this tutorial very interesting, especially when you are new on development. Can help me because I would like each pin to have a different image. I tried but I can not find the answer. thank you in advance

    1. Hey Marc,

      Yes it is possible, can you please check this out. – http://stackoverflow.com/questions/25631410/swift-different-images-for-annotation

      Hope this helps

      1. Hi Ravi,

        Thanks a lot for the time that you have spent. I have kept a look to stackoverflow but our code is pretty different. Can you please provide to us a small example on how to add the image on the .plist file and then call it inside the code?

        It will be super helpful.
        Thank you!

  11. Kyle Suchar Avatar
    Kyle Suchar

    Hi thanks for the great tutorial! How would i go about changing the color of the pins?

    Thanks

  12. Very interesting tutorial but I have a question about the polyline and how to get coordinate values at each point, can you help please?

    I am using the code below to find route between 2 locations and it adds an overlay polyline but I would like the coordination’s of the second point (the first being the start point). The reason is so if somebody has just activated the route, which direct do they have to start walking in, so I will display an arrow.

    let request = MKDirectionsRequest()
    request.source = MKMapItem(placemark: MKPlacemark(coordinate: sourceLocation, addressDictionary: nil))
    request.destination = MKMapItem(placemark: MKPlacemark(coordinate: destinationLocation, addressDictionary: nil))
    request.requestsAlternateRoutes = true
    request.transportType = .walking // .automobile
    let directions = MKDirections(request: request)
    directions.calculate { [unowned self] response, error in
    guard let unwrappedResponse = response else { return }
    if (unwrappedResponse.routes.count > 0) {
    self.mainMapView.add(unwrappedResponse.routes[0].polyline)
    }

    Any help you can offer a newbie would be gratefully received.

  13. how to navigate from one point to another points(Annotations)

  14. Where can I get the plist from?

    1. Hi Pete, You should create a plist file with the mappoints or use the sample plist provided as part of this project – https://github.com/rshankras/MapViewDemo/tree/master/MapViewDemo

Leave a Reply to Ravi Shankar Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.