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)] } }
Leave a Reply