Work with Apple Maps, Google Maps, and Mapbox in iOS with Swift programming. Guided by practical examples, this book covers all three map frameworks to ensure you properly select which one best suits your iOS app''s needs in working with iOS location. You''ll see how Apple''s privacy settings apply to a user''s location, and how to access that user''s location from an application. Once you have access to the user''s location, allow your app to display points of interest from Apple''s database on the map inside the app, as well as to provide a search through that database by name. You can also incorporate turn by turn directions inside your own app to provide routes. Or trigger different functionality or notifications based on locational queues. With Build Location Apps on iOS with Swift, you''ll even find out how to provide offline map support for hiking, camping, or other outdoors applications where cell phone service is weak. What You''ll Learn Display points of interest within your own app Work with Apple''s privacy settings so pertinent information comes through Trigger functionality based on geographic prompts Create your own custom map styles with Mapbox Studio and display them in the app
Build Location Apps on iOS with Swift Use Apple Maps, Google Maps, and Mapbox to Code Location Aware Mobile Apps — Jeffrey Linwood Build Location Apps on iOS with Swift Use Apple Maps, Google Maps, and Mapbox to Code Location Aware Mobile Apps Jeffrey Linwood Build Location Apps on iOS with Swift: Use Apple Maps, Google Maps, and Mapbox to Code Location Aware Mobile Apps Jeffrey Linwood Austin, TX, USA ISBN-13 (pbk): 978-1-4842-6082-1 https://doi.org/10.1007/978-1-4842-6083-8 ISBN-13 (electronic): 978-1-4842-6083-8 Copyright © 2020 by Jeffrey Linwood This work is subject to copyright All rights are reserved by the Publisher, whether the whole or part of the material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation, broadcasting, reproduction on microfilms or in any other physical way, and transmission or information storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now known or hereafter developed Trademarked names, logos, and images may appear in this book Rather than use a trademark symbol with every occurrence of a trademarked name, logo, or image we use the names, logos, and images only in an editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the trademark The use in this publication of trade names, trademarks, service marks, and similar terms, even if they are not identified as such, is not to be taken as an expression of opinion as to whether or not they are subject to proprietary rights While the advice and information in this book are believed to be true and accurate at the date of publication, neither the authors nor the editors nor the publisher can accept any legal responsibility for any errors or omissions that may be made The publisher makes no warranty, express or implied, with respect to the material contained herein Managing Director, Apress Media LLC: Welmoed Spahr Acquisitions Editor: Aaron Black Development Editor: James Markham Coordinating Editor: Jessica Vakili Distributed to the book trade worldwide by Springer Science+Business Media New York, 233 Spring Street, 6th Floor, New York, NY 10013 Phone 1-800-SPRINGER, fax (201) 348-4505, e-mail orders-ny@springer-sbm.com, or visit www.springeronline.com Apress Media, LLC is a California LLC and the sole member (owner) is Springer Science + Business Media Finance Inc (SSBM Finance Inc) SSBM Finance Inc is a Delaware corporation For information on translations, please e-mail booktranslations@springernature.com; for reprint, paperback, or audio rights, please e-mail bookpermissions@springernature.com Apress titles may be purchased in bulk for academic, corporate, or promotional use eBook versions and licenses are also available for most titles For more information, reference our Print and eBook Bulk Sales web page at http://www.apress.com/bulk-sales Any source code or other supplementary material referenced by the author in this book is available to readers on GitHub via the book’s product page, located at www.apress.com/ 978-1-4842-6082-1 For more detailed information, please visit http://www.apress.com/ source-code Printed on acid-free paper Table of Contents About the Author���������������������������������������������������������������������������������ix About the Technical Reviewer�������������������������������������������������������������xi Chapter 1: Creating Your First MapKit App�������������������������������������������1 Getting started������������������������������������������������������������������������������������������������������1 Adding a map��������������������������������������������������������������������������������������������������������5 Adding a pin to your map������������������������������������������������������������������������������10 Summary������������������������������������������������������������������������������������������������������������16 Chapter 2: Getting the User’s Location�����������������������������������������������17 Privacy and location permissions�����������������������������������������������������������������������17 Location permissions in the Info.plist file������������������������������������������������������18 Requesting location permissions from the end user������������������������������������������19 Requesting location updates�������������������������������������������������������������������������22 Displaying the user’s location on the map����������������������������������������������������24 Summary������������������������������������������������������������������������������������������������������������26 Chapter 3: Displaying Annotations on a MapKit Map�������������������������27 Understanding MapKit and annotations��������������������������������������������������������������27 Using a custom annotation class������������������������������������������������������������������������28 Display custom annotations��������������������������������������������������������������������������������29 Customizing pins for annotations�����������������������������������������������������������������������30 Handling the user location����������������������������������������������������������������������������������33 Reusing annotation views�����������������������������������������������������������������������������������33 iii Table of Contents Dequeuing and creating annotation views����������������������������������������������������������35 Setting images on annotation views�������������������������������������������������������������������36 Using callouts with annotations��������������������������������������������������������������������������38 Summary������������������������������������������������������������������������������������������������������������39 Chapter 4: Searching for Points of Interest����������������������������������������41 Getting started with local search������������������������������������������������������������������������41 Exploring the map items in the response�����������������������������������������������������������44 Displaying the search results on a map��������������������������������������������������������������44 Creating annotations for results��������������������������������������������������������������������������47 Filtering with points of interest categories���������������������������������������������������������47 Chapter 5: Getting Directions with MapKit�����������������������������������������53 Understanding the Directions API�����������������������������������������������������������������������53 Getting started with directions���������������������������������������������������������������������������54 Understanding route steps����������������������������������������������������������������������������������61 Building step-by-step directions�������������������������������������������������������������������������62 Displaying the current step���������������������������������������������������������������������������64 Saving the route in an instance variable�������������������������������������������������������66 Actions for the previous and next buttons�����������������������������������������������������67 Next steps�����������������������������������������������������������������������������������������������������������73 Summary������������������������������������������������������������������������������������������������������������74 Chapter 6: Working with Geofences in CoreLocation��������������������������75 Concepts for region monitoring��������������������������������������������������������������������������75 Setting up your location-based application��������������������������������������������������������76 Getting started with region monitoring���������������������������������������������������������������78 Listening for geofence triggers���������������������������������������������������������������������������80 iv Table of Contents Displaying a local notification inside the app�����������������������������������������������������82 Setting up the notification center������������������������������������������������������������������82 Displaying a local notification for a region����������������������������������������������������84 Monitoring region changes in the app delegate��������������������������������������������85 Removing geofences from the app���������������������������������������������������������������������87 Chapter 7: Displaying a Map with the Google Maps SDK�������������������89 Using the Google Maps Platform�������������������������������������������������������������������������89 Installing the Google Maps SDK for iOS library���������������������������������������������������90 Setting up a Google Maps API Key����������������������������������������������������������������������93 Including the API Key in your application������������������������������������������������������������98 Displaying Google Maps with a map view����������������������������������������������������������99 Allowing the Google Maps and Chrome URL schemes�������������������������������������102 Changing display options on the map view������������������������������������������������������103 Chapter 8: Exploring Google Map Views�������������������������������������������107 Changing the type of map tiles�������������������������������������������������������������������������107 Displaying map markers�����������������������������������������������������������������������������������108 Changing the marker icon���������������������������������������������������������������������������110 Responding to marker events���������������������������������������������������������������������110 User data and markers��������������������������������������������������������������������������������111 Adding shapes to the map��������������������������������������������������������������������������������112 Circles����������������������������������������������������������������������������������������������������������113 Polylines and paths�������������������������������������������������������������������������������������114 Polygons������������������������������������������������������������������������������������������������������117 Removing markers and shapes������������������������������������������������������������������������119 Conclusion��������������������������������������������������������������������������������������������������������119 v Table of Contents Chapter 9: Using Directions with the Google Directions API������������121 Setting up the Google Directions API����������������������������������������������������������������122 Restricting the API Key��������������������������������������������������������������������������������������124 Using the Google Directions API������������������������������������������������������������������������126 Creating the URL�����������������������������������������������������������������������������������������������127 Calling the Directions API with URLSession������������������������������������������������������128 Processing the directions response������������������������������������������������������������������130 Displaying the route as a polyline���������������������������������������������������������������������135 Updating the map bounding box�����������������������������������������������������������������������136 Next steps: Displaying each leg and step���������������������������������������������������������138 Chapter 10: Using Google Places in Your iOS App����������������������������139 Building a places finder with a map�����������������������������������������������������������������139 Creating the project������������������������������������������������������������������������������������������140 Getting a Google Places API key�����������������������������������������������������������������������140 Setting up CocoaPods���������������������������������������������������������������������������������������145 Providing an API key for Google Places and Google Maps��������������������������������147 Creating the user interface�������������������������������������������������������������������������������148 Understanding the autocomplete search����������������������������������������������������������151 Creating the autocomplete view controller�������������������������������������������������152 Setting geographic boundaries for the search��������������������������������������������152 Requesting a subset of data fields��������������������������������������������������������������153 Filtering results by type�������������������������������������������������������������������������������155 Displaying the view controller���������������������������������������������������������������������156 Implementing the delegate for autocomplete���������������������������������������������158 Displaying the place on the map�����������������������������������������������������������������������160 Additional functionality in Places SDK��������������������������������������������������������������162 vi Table of Contents Chapter 11: Getting Started with the Mapbox SDK���������������������������165 Getting a Mapbox access token������������������������������������������������������������������������165 Starting a new project with the Mapbox SDK���������������������������������������������������167 Displaying a map view��������������������������������������������������������������������������������������170 Customizing the map view’s appearance���������������������������������������������������������172 Display a point annotation on the map�������������������������������������������������������������174 Chapter 12: Customizing Map Styles with Mapbox��������������������������179 Getting ready for map styles�����������������������������������������������������������������������������179 Changing the default style on the map view�����������������������������������������������������180 Creating map styles with Mapbox Studio���������������������������������������������������������180 Displaying the new map style in the app����������������������������������������������������������191 Chapter 13: Working with Datasets in Mapbox Studio���������������������193 Earthquake map������������������������������������������������������������������������������������������������193 Downloading the earthquake data��������������������������������������������������������������������194 Creating a dataset on Mapbox Studio���������������������������������������������������������������197 Creating a tileset�����������������������������������������������������������������������������������������������204 Adding the tileset to a style������������������������������������������������������������������������������206 Styling the features with Mapbox Studio����������������������������������������������������������208 Displaying the dataset in the app���������������������������������������������������������������������215 Detecting a tap on the features������������������������������������������������������������������������217 Conclusion��������������������������������������������������������������������������������������������������������218 Chapter 14: Turn-by-Turn Navigation with Mapbox��������������������������221 Setting up your app project������������������������������������������������������������������������������222 Setting up CocoaPods���������������������������������������������������������������������������������222 Adding entries to Info.plist��������������������������������������������������������������������������223 Adding required capabilities������������������������������������������������������������������������223 vii Table of Contents Using the Mapbox Directions API����������������������������������������������������������������������225 Displaying the navigation user interface����������������������������������������������������������228 Using the Mapbox simulated navigation�����������������������������������������������������������231 Customizing the navigation experience������������������������������������������������������������233 Conclusion��������������������������������������������������������������������������������������������������������234 Chapter 15: Using Offline Maps with Mapbox����������������������������������235 Setting up your app project������������������������������������������������������������������������������235 Understanding offline map downloading����������������������������������������������������������236 Estimating the number of tiles used�����������������������������������������������������������������237 Downloading an offline map pack��������������������������������������������������������������������238 Monitoring offline map pack downloads�����������������������������������������������������������242 Considerations for using offline map tiles��������������������������������������������������������247 Index�������������������������������������������������������������������������������������������������249 viii About the Author Jeffrey Linwood is an experienced software developer who has worked on many iOS and Android apps that use maps or location functionality He’s also taught and mentored college student application teams as they develop their first iOS apps While teaching, he noticed a lack of good sample applications and tutorials for map and location applications Jeff also enjoys running, hiking, and spending time with his wife, Clover, in Austin, Texas You can follow Jeff on Twitter at @jefflinwood, or on his blog, https://www.jefflinwood.com ix Chapter 15 Using Offline Maps with Mapbox To create your own bounds, create a function in your ViewController class from the code in Listing 15-2 – these coordinates define an area in Central Texas, the same ones we used for the offline map tile estimator Listing 15-2. Creating offline region bounds func createOfflineRegionBounds() -> MGLCoordinateBounds { let southwest = CLLocationCoordinate2D( latitude: 28.822, longitude: -99.5934) let northeast = CLLocationCoordinate2D( latitude: 30.8611, longitude: -96.6051) return MGLCoordinateBounds(sw: southwest, ne: northeast) } The preceding method returns an MGLCoordinateBounds structure You can also call mapView.visibleCoordinateBounds to get the bounds for the map displaying in the map view You might know that your application serves a certain geographic area, in which case you might want to define fixed coordinates Or you may let the user decide which tiles to download by picking an area out on the map themselves and then tapping a download button Once you have a set of bounds, you can create an MGLTilePyramidOfflineRegion region These are the only types of offline regions you can create They take the bounds, the minimum map zoom level, and the maximum map zoom level, as well as the map style to use Typically, you would use the same map style as the map view, but you could specify another style URL if you like 239 Chapter 15 Using Offline Maps with Mapbox An example of creating a region looks like this: let region = MGLTilePyramidOfflineRegion( styleURL: mapView.styleURL, bounds: bounds, fromZoomLevel: 5, toZoomLevel: 8) We will use this code snippet in a method that downloads an offline map pack, so don’t put it into your class yet The next step is to add an offline map pack The MGLOfflineStorage class is a singleton (accessed with MGLOfflineStorage.shared) that you can call the addPack method on This method takes the region, a context, and a completion handler The context argument is a general-purpose storage variable that takes a Data instance You can put anything you like into the context We’re going to take the simple approach and store a string as the context with UTF-8 encoding The completion handler takes the offline pack and an error as optional arguments Once you get the offline pack, call the resume() method on the pack to start the download process The complete method to download an offline map pack is in Listing 15-3 Add the downloadOfflineMapPack() method to your ViewController class To test your code, call this method at the end of your viewDidLoad() method Listing 15-3. Download an offline map pack func downloadOfflineMapPack() { let bounds = createOfflineRegionBounds() let region = MGLTilePyramidOfflineRegion( styleURL: mapView.styleURL, bounds: bounds, fromZoomLevel: 5, toZoomLevel: 8) 240 Chapter 15 Using Offline Maps with Mapbox let packName = "Central Texas" guard let nameData = packName.data(using: utf8) else { return } MGLOfflineStorage.shared.addPack( for: region, withContext: nameData) { (pack, error) in guard let pack = pack else { print("Unable to create pack") print(error?.localizedDescription ?? "No error given") return } pack.resume() } } You can specify your own offline map pack name; it is only used for reference by your own project You could store a GUID there or a dictionary of name/value attributes Typically, you will want to know when the download process is finished, or you may want to display progress to the user Let’s take a look at the notifications that get sent when the Mapbox SDK downloads an offline map pack The complete code for the view controller is in Listing 15-4, if you want to see how each of the pieces fits together 241 Chapter 15 Using Offline Maps with Mapbox Monitoring offline map pack downloads There are three different notifications that the offline map downloader will send out These are standard iOS notifications, monitored with the NotificationCenter, not to be confused with push notifications: • MGLOfflinePackProgressChanged • MGLOfflinePackError • MGLOfflinePackMaximumMapboxTilesReached Let’s focus on the progress changed notification We need to subscribe to these progress changed notifications in our viewDidLoad() method Add the code in the following snippet to your viewDidLoad() method: NotificationCenter.default.addObserver( self, selector: #selector(offlinePackProgressChanged), name: NSNotification.Name.MGLOfflinePackProgressChanged, object: nil) We also need to define that offlinePackProgressChanged method and make sure it has an @objc annotation Add the following function definition to your class: @objc func offlinePackProgressChanged( notification: NSNotification) { print("Offline pack progress changed") } If you go ahead and add the notification, observer in the viewDidLoad() method, and then add the offlinePackProgressChanged() method, run the app in the Simulator You will see many print statements showing that something is happening! 242 Chapter 15 Using Offline Maps with Mapbox If we want to get more details, we can get those from the notification The optional object property of the notification is the offline pack The offline pack has a property named progress that is an MGLOfflinePackProgress structure Let’s print out those completed bytes to the console: @objc func offlinePackProgressChanged( notification: NSNotification) { guard let pack = notification.object as? MGLOfflinePack else { return } print("Offline pack progress changed") print(pack.progress.countOfBytesCompleted) } Modifying the function to show this will give us more information about the progress of the application, but of course isn’t quite ready for the end users yet They would probably like to see some kind of percentage, letting them know that they are close to the finish You can set this up with a progress view, but for now we will simply print the percentages out, to the console Add the following to the end of the offlinePackProgressChanged method: let percentageResources = Int(round(100 * Float(progress.countOfResourcesCompleted) / Float(progress.countOfResourcesExpected))) print("Resources: \(percentageResources)%") 243 Chapter 15 Using Offline Maps with Mapbox To use this with a progress view, you could simply set the progress value of the progress view to be the number of resources completed divided by the number of resources expected: progressView.progress = Float(progress countOfResourcesCompleted) / Float(progress.countOfResourcesExpected))) Once the count of resources completed equals the number of count expected, you could dismiss the progress bar with a timer and optionally pop up an alert view Once we combine all of our code together, we end up with a view controller class, that will display a Mapbox map, but all of the download progress will be displayed on the console for debugging The complete code listing for the ViewController class is in Listing 15-4 Listing 15-4. Complete ViewController class import UIKit import Mapbox class ViewController: UIViewController { @IBOutlet weak var mapView: MGLMapView! var progressView: UIProgressView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view mapView.centerCoordinate = CLLocationCoordinate2D( latitude: 30.2, longitude: -97.75) mapView.zoomLevel = 10 mapView.styleURL = MGLStyle.outdoorsStyleURL 244 Chapter 15 Using Offline Maps with Mapbox NotificationCenter.default.addObserver( self, selector: #selector(offlinePackProgressChanged), name: NSNotification.Name MGLOfflinePackProgressChanged, object: nil) downloadOfflineMapPack() } @objc func offlinePackProgressChanged( notification: NSNotification) { guard let pack = notification.object as? MGLOfflinePack else { return } let progress = pack.progress print("Offline pack progress changed") print(progress.countOfBytesCompleted) let percentageResources = Int(round(100 * Float(progress.countOfResourcesCompleted) / Float(progress.countOfResourcesExpected))) print("Resources: \(percentageResources)%") } func createOfflineRegionBounds() -> MGLCoordinateBounds { let southwest = CLLocationCoordinate2D( latitude: 28.822, longitude: -99.5934) let northeast = CLLocationCoordinate2D( latitude: 30.8611, longitude: -96.6051) 245 Chapter 15 Using Offline Maps with Mapbox return MGLCoordinateBounds(sw: southwest, ne: northeast) } func downloadOfflineMapPack() { let bounds = createOfflineRegionBounds() let region = MGLTilePyramidOfflineRegion( styleURL: mapView.styleURL, bounds: bounds, fromZoomLevel: 5, toZoomLevel: 8) let packName = "Central Texas" guard let nameData = packName.data(using: utf8) else { return } MGLOfflineStorage.shared.addPack( for: region, withContext: nameData) { (pack, error) in guard let pack = pack else { print("Unable to create pack") print(error?.localizedDescription ?? "No error given") return } pack.resume() } } } 246 Chapter 15 Using Offline Maps with Mapbox Considerations for using offline map tiles When you set up an application to use offline map tiles, there are several constraints to consider The first is pricing Make sure that you have an idea of how many tiles each user will download and how that fits into your budget Use this number to drive the maximum zoom level or the maximum size of the map region Also consider how long it will take for the user to perform the download If you block the user from continuing into the application while the map tiles download, provide a progress bar or some other user interface If the number of map tiles is large, let the user know that they should initiate the process themselves when they have access to a wireless Ethernet network, unless they want to incur large bandwidth charges from their carrier Mapbox does provide some soft limits to how many map tiles a user can download That number is currently 6000 map tiles across all downloaded regions, but you can raise it yourself by calling the setMaximumAllowedMapboxTiles method on the MGLOfflineStorage class Once you bump up against the built-in limit or the limit that you set, the Mapbox SDK will post the MGLOfflinePackMaximumMapboxTilesReached notification You can listen for that notification similarly to how we listened for offline map tile download progress Your app will have to remove existing offline map packs to continue downloading map tiles into a new pack if the limit is reached Last, Mapbox does not allow offline map tiles to be redistributed from the app (for instance, to another copy of the app on another user’s phone), so read the terms of service to make sure that your app’s overall design works with Mapbox’s solution 247 Index A, B addMarker method, 112, 161 API key AppDelegate.swift, 98 bundle identifier, 96 create credentials, 95 creating project, 94 creation dialog box, 96 Google Maps Platform, 93 iOS Maps, 98 restriction, 97 runtime error, 98 Apple’s local search guard let, 44 naturalLanguageQuery, 42 pointOfInterestFilter, 42 region, 42 resultTypes, 42 searching for points of interest, 43 start method, 43 web-accessible API, 41 application(_:didFinishLaunching WithOptions:) method, 147 Application programming interfaces (APIs), © Jeffrey Linwood 2020 J Linwood, Build Location Apps on iOS with Swift, https://doi.org/10.1007/978-1-4842-6083-8 autocompleteBounds property, 153 autocompleteFilter property, 155 C calculate()/calculateETA() method, 54, 56 canShowCallout property, 38 Category filter, map annotations, 49, 50 CocoaPods, 222 dependency manager, 90 installation, 91 NPM, 90 Podfile, 91, 92 Xcode workspace, 92, 93 Codable protocol, 127 coordinate property, 28 CoreLocation framework, 17, 20, 26 createWaypoints() method, 227 Creating annotation, search result, 47 Custom annotation class init method, 28 map view, 30 249 Index D, E F dequeueReusable AnnotationView() function, 33 Directions API calculate() method, 54, 56 displaying route, 59, 60 getDirections() method, 55 MapKit classes, 53 map view, 61 MKDirections.Request object, 54 MKPolylineRenderer, 58 MKRoute objects, 54 polyline, 57 transportation type, 56 viewDidLoad() method, 54 displayCurrentStep() method, 64, 66, 67 Displaying map markers callback method, 110, 111 iconView property, 110 info window, 109 userData property, 112 ViewController class, 44, 46, 108 viewDidLoad() method, 109 displayNotification() function, 84 displayOverviewPolyline() method, 134 downloadOfflineMapPack() method, 240 findBusinesses() method, 157 250 G, H Geofence triggers CLLocationManagerDelegate protocol, 80 iOS Simulator, 81, 82 RESTful resource, 81 viewDidLoad() method, 80 getDirections() method, 54–56, 58, 227 GMSAutocomplete ResultsViewController Delegate protocol, 158 GMSCircle class, 113, 114 GMSMapViewDelegate protocol, 110 GMSMarker class, 110 GMSMutablePath object, 114 GMSPolyline object, 115, 116 Google Directions API definition, 121 Google Cloud Platform console, 138 JSONDecoder, 130–134 JSONSerialization class, 127 map bounding box, 136 polyline, dislaying route, 135 RESTRICT KEY, 124, 125 setting up, 122–124 INDEX URL, creating, 127, 128 URLSession, 127–129 Google Maps API Key (see API key) changing display options, 103–105 Chrome URL schemes, 102, 103 CocoaPods (see CocoaPods) iOS app, 89 map view, 100 marker (see Displaying map markers) platform, 89, 90 simulator, 101 Google Places, iOS apps additional functionality, 162 API key, 140, 142–145 autocomplete search data fields, 153, 154 elements, 151 filtering results, 155 full-screen view controller, 151 geographic boundaries, 152, 153 implementation, 158–160 view controller, 152, 156, 157 CocoaPods, setting up, 145, 146 creating project, 140 Google Maps, 139 Google Maps SDK, 147, 148 MapKit map, 160–162 user interface, creating, 148–151 I, J iconView property, 110 Info.plist file, 223 delegate/view controller, 18 location privacy, 19 Xcode, 18 K Key-value observing (KVO), 28 L Local notification app delegate, 85 AppDelegate class, 82 CoreLocation manager, 86 iPhone Simulator, 87 monitoring region, 84, 85 setting up center, 83, 84 Location-based application Info.plist file, 76 permission description, 78 ViewController class, 77 M Mapbox Directions API, 225, 226 Mapbox library, 169 Mapbox Navigation framework, 221 capabilities, 223, 224 cocoaPods, 222, 223 251 INDEX Mapbox Navigation framework (cont.) Info.plist file, 223 set up, 222 Mapbox SDK access token, 165, 166 annotations, 174–176, 178 customizing map view, appearance, 172, 173 map view, 170, 172 project, 167–169 Mapbox Studio, datasets dataset, creating, 197, 199–204 detecting tap, features, 217, 218 displaying app, 215–217 earthquake data, downloading, 194, 195, 197 Earthquake map, 193 features, 208–210, 212–215 tileset, adding style, 206, 207 tileset, creating, 204–206 MapKit framework MKAnnotation protocol, 27 MKMarkerAnnotationView class, 28 MKPinAnnotationView class, 28 MKPointAnnotation class, 27 Map styles default style, changing, 180 iOS app, 191, 192 Mapbox SDK, 179 Mapbox Studio, 180–186, 188–191 252 mapTapped(sender:)) method, 218 mapType property, 119 mapView: annotationCanShowCallout function, 174 mapView(_:viewFor:) function, 30, 31 markerImage() method, 110 MGLMapViewDelegate protocol, 175 MKAnnotation protocol, 28, 29, 44 MKDirections.Response, 54 MKDirectionsTransportType struct, 56 MKMapItem class, 51 MKMapItem map, 43 MKMapItem objects, 44 MKMapView class annotation reuse/creation, 35 callouts, 38 registerClass:forAnnotationView WithReuseIdentifier: function, 35 UIImage, 37 MKMapViewDelegate protocol, 35, 57, 58 MKMapView map adding constraints, assistant view, 11 controller’s view, creating outlet, 12 iOS app, 10, 15 MKAnnotationView class, 13 INDEX naming outlet, 12 object library, storyboard, ViewController class, 14 viewDidLoad() method, 13 MKPinAnnotationView class display, blue pins, 32 MKMapViewDelegate, 30 pin annotation view, 31 viewDidLoad() method, 30 MKPointOfInterestCategory struct, 48 MKPolyline, 57 MKRoute.Step objects print to console, 62 properties, 62 MKUserLocation annotation, 33, 34 N Navigation user interface, 228–230 customize, 233, 234 simulation, 231–233 Node Package Manager (NPM), 90 NSObject class, 28 O @objc annotation, 218 Offline map, 235 app set up, 236 constraints, 247 controller class, 244, 246 download, 236, 238–241 notifications, 242, 243 tile count, 237, 238 P, Q placeFields property, 154 Polygons addPolygon() method, 118 GMSPolygon class, 117 path of coordinates, 117 provideAPIKey() method, 147 R Region monitoring CLCircularRegion.self, 79 CLRegion, 79 creating geofence, 79, 80 Region monitoring CoreLocation Manager, 75 end user allows permission, 76 20 geofences, 75 iOS, 76 location permission, 76 Removing geofences, 87, 88 Removing markers/shapes, 119 Requesting location permissions CLLocationManager object, 19 CoreLocation, 20 displaying user’s location on map, 24–26 Info.plist file, 19 iOS, 21 ViewController class, 22, 24 253 INDEX retrieveDirections() method, 129 Reusable annotation views, 39 S startNavigation() method, 229 Step-by-step directions create function, 64 currentRoute instance variable, 66 displayCurrentStep() method, 64, 67 functionality, 65 next() action, 68 padding, 66 previous() action, 67 route step, 66 user interface elements, 62–64 ViewController class, 69, 71–73 styleURL property, 180, 216 Swift programming language, T Transportation types, 73 Turn-by-turn navigation, 230 254 U User’s location functionality, 17 privacy/location permissions, 17–19 V, W viewDidLoad() method, 20, 29, 46, 113, 118, 173–175, 218, 228, 240 viewFor() method, 35, 37 X, Y, Z Xcode APIs, installation, iOS app, iOS simulators, 4, Mac App Store, Single View Application, SwiftUI check box, .. .Build Location Apps on iOS with Swift Use Apple Maps, Google Maps, and? ?Mapbox to? ?Code Location Aware Mobile Apps Jeffrey? ?Linwood Build Location Apps on iOS with Swift: Use Apple Maps, Google. .. have a compelling reason to get the user’s location, the user is very likely to not allow the app access © Jeffrey Linwood 2020 J Linwood, Build Location Apps on iOS with Swift, https://doi.org/10.1007/978-1-4842-6083-8_2... the User’s Location If your app relies on using the user’s location in the background, iOS will pop up a confirmation alert to the user that says your app is continuing to use their location in