Make App Pie

Training for Developers and Artists

Use Markers Instead of Pins for Map Annotations

iOS Development tips weekly is a series you can find at the Lynda.com and LinkedIn Learning libraries. The first week of a week’s tip will be available to the public. After that, you will need a subscription to get access to it. Click the image the left  to view.

For as long as there has been a map in iOS, there has been pins. The map of Pizza restaurants in Chicago I have here has those multicolored pins you’ve seen before.

While you can still use them, iOS11 changes pins to something far more flexible and useful: markers. I’ll show you how to use markers.
You’ll find a starter file on GitHub. When you open the code, you’ll find a model of pizza annotations which creates an array of Pizza restaurants as annotations. If you want to learn more take a look at the course Advanced iOS App Development: MapKit and Core Location. I’m going to assume you’re familiar with annotations.

To get a marker, I change the MKPinAnnotationView to MKMarkerAnnotationView. The first place to do that defines the view in the delegate method:

var annotationView = MKPinAnnotationView()

I’ll change the to a marker view

var annotationView = MKMarkerAnnotationView()

There’s two more down the code for dequeuing or creating the view.

if let dequedView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKPinAnnotationView {
annotationView = dequedView
} else{
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
}

I’ll change those to markers too.

if let dequedView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKMarkerAnnotationView {
    annotationView = dequedView
} else{
    annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: identifier)
}

There is no pin tint color property. Instead, Marker annotations have a marker tint color.Change the pin tint to a marker tint:

annotationView.markerTintColor = color

Run this using a iPhone 8 Plus simulator. You now have the balloon markers with pin glyphs.

Double tap on the map to zoom in near the black marker. Under the marker is the title with the restaurant name.

If you click on the marker, It expands, and the subtitle appears.

Close the app. You can customize the marker several ways. Under the marker tint, add

annotationView.glyph

You’ll see several selections,

You can add your own glyphs, an image that appears instead of the a pin inside the balloon. Glyphs can be text, emoji, or 40 point by 40 point images. Like tab bar images, these images are determined by their alpha channel only.

I’ve made an image for you in the assets folder named pizza. Finish the line by adding a glyph image to the
UImage pizza.

annotationView.glyphImage = UIImage(named: "pizza")

You can change the glyph tint color too. It defaults to white, but I’ll make it yellow.

annotationView.glyphTintColor = .yellow

Run the app again, and you’ll see icons for the pizza types.

Now notice the marker in downtown Chicago, between the C and H of the word Chicago. Double Click or zoom in a few times and the one marker will split into three.

Markers, unlike pins will not crowd your map. When there are some too close together, they will cluster. Stop the app and under the glyphTintColor, add the following:

annotationView.clusteringIdentifier = identifier

The clusteringIdentifier property clusters markers. If there a few of the same indentifier next to each other, it replaces the cluster of markers with a single marker with a glyph indicating the number of markers there.
Run this. You’ll see a 3.

Zoom in on the 3 marker, and the three markers appear.

As you Zoom out, you see new markers show up.

Zoom out enough and Only one restaurant is left.

There’s more you can do with markers, but this gives you a good idea to get a less cluttered, better looking map than you can with pins.

 

The Whole Code

You can find a completed project here on Github.  Below is the code for the pizza locations and view controller classes.

ViewController.swift

//
//  ViewController.swift
//  ChiPizzaLocations
//
//  Created by Steven Lipton on 11/3/17.
//  Copyright © 2017 Steven Lipton. All rights reserved.
//

import UIKit
import MapKit


class ViewController: UIViewController, MKMapViewDelegate {
    let pizzaAnnotations = PizzaAnnotations()
    let initialCoordinate = CLLocationCoordinate2DMake(41.9180474,-87.661767)
    @IBOutlet weak var mapView: MKMapView!
    
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        var annotationView = MKMarkerAnnotationView()
        guard let annotation = annotation as? PizzaAnnotation else {return nil}
        var identifier = ""
        var color = UIColor.red
        switch annotation.type{
        case .deepDish:
            identifier = "Deep Dish"
            color = .red
        case .potPie:
            identifier = "Pot pie"
            color = .black
        case .thin:
            identifier = "Thin crust"
            color = .blue
        }
        if let dequedView = mapView.dequeueReusableAnnotationView(
            withIdentifier: identifier)
            as? MKMarkerAnnotationView {
            annotationView = dequedView
        } else{
            annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: identifier)
        }
        annotationView.markerTintColor = color
        annotationView.glyphImage = UIImage(named: "pizza")
        annotationView.glyphTintColor = .yellow
        annotationView.clusteringIdentifier = identifier
        return annotationView
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        mapView.delegate = self
        //set intial region
        let initialregion = MKCoordinateRegion(center: initialCoordinate, span: MKCoordinateSpanMake(0.25, 0.25))
        mapView.setRegion(initialregion, animated: true)
        // add the annotations
        mapView.addAnnotations(pizzaAnnotations.restaurants)
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

PizzaLocations.swift

//
//  PizzaLocations.swift
//  ChiPizzaLocations
//
//  Created by Steven Lipton on 11/3/17.
//  Copyright © 2017 Steven Lipton. All rights reserved.
//

import UIKit
import MapKit

enum PizzaType {
    case thin
    case deepDish
    case potPie
}

class PizzaAnnotation:NSObject,MKAnnotation{
    var coordinate: CLLocationCoordinate2D
    var title: String?
    var subtitle: String?
    var type: PizzaType
    init(_ latitude:CLLocationDegrees,_ longitude:CLLocationDegrees,title:String,subtitle:String,type:PizzaType){
        self.coordinate = CLLocationCoordinate2DMake(latitude, longitude)
        self.title = title
        self.subtitle = subtitle
        self.type = type
    }
}


class PizzaAnnotations: NSObject {
    var restaurants:[PizzaAnnotation]
    
    override init(){
       //build an array of pizza loactions literally
        restaurants = [PizzaAnnotation(41.892472,-87.62687676, title: "Pizzeria Uno", subtitle:"First Deep Dish Pizza", type: .deepDish)]
        restaurants += [PizzaAnnotation(41.8931164,-87.6267778, title: "Pizzeria Due", subtitle:"Second Uno Location", type: .deepDish)]
        restaurants += [PizzaAnnotation(41.8957338,-87.6229457, title: "Gino's East", subtitle:"Deep Dish if you can't cross Michigan Avenue", type: .deepDish)]
        restaurants += [PizzaAnnotation(41.9206924,-87.6375364, title: "Chicago Pizza and Oven Grinder", subtitle:"Pizza baked in a bowl", type: .potPie)]
         restaurants += [PizzaAnnotation(41.9217837,-87.6645778, title: "Pequods", subtitle:"Carmelized Crust Deep Dish", type: .deepDish)]
         restaurants += [PizzaAnnotation(42.0018732,-87.7258586 , title: "Lou Malnati's", subtitle:"Ex Uno's Manager goes solo", type: .deepDish)]
         restaurants += [PizzaAnnotation(41.8910953,-87.6597941 , title: "CoalFire", subtitle:"Coal fired thin pizza", type: .thin)]
         restaurants += [PizzaAnnotation(41.9105463,-87.6760223, title: "Piece", subtitle:"White, thin square pizza", type: .thin)]
         restaurants += [PizzaAnnotation(41.9633682,-87.6737948, title: "Spacca Napoli", subtitle:"Authentic Neopolitan pizza", type: .thin)]
    }
}

One response to “Use Markers Instead of Pins for Map Annotations”

  1. […] Use Markers Instead of Pins for Map Annotations […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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

%d bloggers like this: