How To Create A Service Area Map
Update note: Andrew Tetlaw updated this tutorial for iOS xiii. Audrey Tam wrote the original.
MapKit is a powerful API available on iOS devices that makes it easy to display maps, mark locations, enhance with custom data and even draw routes or other shapes on elevation.
In this MapKit tutorial, yous'll make HonoluluArt, an app that zooms into a location in Honolulu and marks public artwork on a map. Y'all'll implement the marker's callout detail button to launch the Maps app and open driving directions to the artwork. Then, you'll parse a GeoJSON file from the Honolulu metropolis data portal to extract the public artwork features and mark them on the map.
In the procedure, you'll learn how to:
- Add together a MapKit map to your app.
- Zoom to a particular location.
- Parse GeoJSON data to create custom map annotations.
A notation from the original author, Audrey Tam: This update uses public artworks data from Honolulu, where I was born and raised. Information technology's no longer my hometown, but the names and places bring back memories. If you're not lucky enough to live there, I hope you'll enjoy imagining yourself being there!
Getting Started
To get started, download the starter project using the Download Materials button at the tiptop or lesser of this tutorial. The project contains a GeoJSON file and some paradigm assets, but no maps yet!
Open up Main.storyboard and, from the Object library, drag a Map Kit View into the middle of the scene. Constrain the Map View to the super view (not the Rubber Area), setting 0 on all edges, so it stretches throughout the Rubber Area of notched devices.
Build and run. You at present have a fully zoomable and panable map showing the continent of your current location using Apple Maps!
So far, so good, eh?
But you don't want to start the map looking at the entire world, unless you're a super-villain, cue evil laugh… You want to zoom into a particular area. And to do that, you demand to go coding!
Open up ViewController.swift and add the following beneath the import UIKit
argument:
import MapKit
Next, you'll demand an outlet for the MKMapView
in ViewController.swift.
Add the post-obit outlet lawmaking immediately before viewDidLoad()
:
@IBOutlet private var mapView: MKMapView!
Then, go to Main.storyboard and link the Map View to your new outlet:
Setting the Visible Area
Go back to ViewController.swift, detect viewDidLoad()
and add together the following to the terminate of the method:
// Set initial location in Honolulu let initialLocation = CLLocation(breadth: 21.282778, longitude: -157.829444)
You'll use this to set the starting coordinates of the map view to a betoken in Honolulu.
When telling the map what to display, giving latitude and longitude is plenty to center the map. But, you must likewise specify the rectangular region to display to get a right zoom level.
Add the following private extension at the finish of ViewController.swift:
private extension MKMapView { func centerToLocation( _ location: CLLocation, regionRadius: CLLocationDistance = g ) { let coordinateRegion = MKCoordinateRegion( heart: location.coordinate, latitudinalMeters: regionRadius, longitudinalMeters: regionRadius) setRegion(coordinateRegion, blithe: truthful) } }
The location
argument is the eye betoken. The region will have north-southward and due east-west spans based on a altitude of regionRadius
, which has a default of 1000 meters, a little more than half a mile, which works well for plotting the public artwork information in the GeoJSON file.
setRegion(_:blithe:)
tells MKMapView
to brandish the region represented by MKCoordinateRegion
. The map view automatically transitions the electric current view to the desired region with a slap-up zoom blitheness, with no extra lawmaking required!
Back in viewDidLoad()
, add the following line to the end of the method:
mapView.centerToLocation(initialLocation)
This calls the helper method to zoom into initialLocation
on startup.
Build and run. You lot'll find yourself in the centre of Waikiki. Aloha! :]
Constraining the Photographic camera
And so far, you've been able to become anywhere you desire on the map, merely we're only interested in the island of Oahu. You've also been able to pinch in to zoom the map so far that the island is merely a few pixels! MapKit is capable of constraining the user to pan and zoom the map over a specified area.
Note: To zoom in the Simulator, hold Selection and elevate in the map view.
Once again in viewDidLoad()
, add the following lines to the end of the method:
let oahuCenter = CLLocation(breadth: 21.4765, longitude: -157.9647) let region = MKCoordinateRegion( center: oahuCenter.coordinate, latitudinalMeters: 50000, longitudinalMeters: 60000) mapView.setCameraBoundary( MKMapView.CameraBoundary(coordinateRegion: region), animated: truthful) let zoomRange = MKMapView.CameraZoomRange(maxCenterCoordinateDistance: 200000) mapView.setCameraZoomRange(zoomRange, animated: true)
Build and run. Now when you lot zoom out, you can't make Oahu every bit small as before. You tin can merely pan the map view to run into the northern, southern, eastern and westernmost edges of the isle.
MapKit uses an internal camera to decide where the signal of view for the map is, how expansive the field of view is and to animate view movement. When you lot specify a photographic camera boundary with a center and a region rectangle, the camera center always stays within this region.
If the user tries to pan further out of the region, the view doesn't scroll any further. Information technology keeps them focused on the area you desire them to see. A region size of 60,000 meters wide by 50,000 meters high keeps Oahu nicely constrained inside the map view.
The MapKit view camera keeps rail of its distance from the view center when zooming in and out. Setting the camera zoom range maximum center distance constraint limits how far the view zooms out and how tiny the island of Oahu becomes. This is even more than helpful when adding points of involvement to the map, which is the next step!
Obtaining Public Art Data
The adjacent step is to plot interesting data effectually the electric current location. Just where in the world tin can you get such stuff?
Well, it depends on your current location. Honolulu, similar many cities, has an Open Data Portal to improve public access to government information.
1 convenient feature of Honolulu's information portal is the ability to export the data prepare in GeoJSON format — a flavor of JSON that'south used to represent geospatial features along with their metadata. One of MapKit'southward recent features makes it super-easy to use GeoJSON information in your app, as yous'll shortly see.
Note: After you end this tutorial, look around to meet if a nearby urban center has another dataset in GeoJSON format you can use. Once you lot come across how easy it is, you may find it interesting plotting different datasets together on the aforementioned map.
For this tutorial, you lot'll use the Honolulu Public Art dataset. To keep things unproblematic, I've already exported this data from the portal and included information technology in the starter project, nicely formatted for readability, of course. Information technology's the least I could do.
To become a feeling for the items in this dataset, open PublicArt.geojson in the Xcode editor. At the top level you'll see:
{ "type": "FeatureCollection", "features": [ ... ] }
The value for the key features
is an array of GeoJSON objects of the type Feature
. Each ane of these objects contains some standard keys, but also a properties
lexicon with some custom fields created past the data portal. The geometry
key is where y'all'll find the coordinates of the characteristic.
Have a look at the first one:
{ "blazon":"Feature", "properties":{ "location":"Lester McCoy Pavilion", "latitude":"21.290824", "description":"...", "thumb":goose egg, "credit":"Funded past the Works Progress Administration", "objectid":"1930.01.01", "creator":"Robert Lee Eskridge", "longitude":"-157.85131", "imagefile":"http://....JPG", "date":"1935", "discipline":"Mural", "championship":"The Makahiki Festival - The Makai Mural", "access":"Express" }, "geometry":{ "type":"Point", "coordinates":[-157.85131,21.290824] } }
GeoJSON Backdrop
Endeavour not to become likewise worried about the GeoJSON data format. Every bit you'll soon encounter, importing information technology is more often than not automated! The essential parts are the properties dictionary and the coordinates.
For this tutorial, yous'll only utilize a few properties: The artwork'due south location name, discipline, title, latitude and longitude:
- Location name: Lester McCoy Pavilion.
- Discipline: Landscape.
- Title: The Makahiki Festival – The Makai Mural.
- Latitude: 21.290824.
- Longitude: -157.85131.
Note: If you want to learn more nearly the format, there'southward a whole world to explore. The official website is a fleck sparse, the RFC is highly technical, but the Wikipedia article is readable. :]
It's a widely supported format for all things geospatial. Some useful tools include geojson.io, a useful site for testing and editing GeoJSON data, and GitHub, which volition automatically render whatsoever .geojson file in a repository on a map.
Later in this tutorial, you'll use the whole dataset. But first, to jump direct into the MapKit fun, you'll plot one of the artworks on the map.
Showing Artwork on the Map
In PublicArt.geojson, press Command-L and leap to line 1354. It'southward a statuary statue of King David Kalakaua in Waikiki Gateway Park.
The backdrop for this item are:
- Location proper name: Waikiki Gateway Park
- Discipline: Sculpture
- Title: King David Kalakaua
- Latitude: 21.283921
- Longitude: -157.831661
To show this on the map view, y'all must create a map annotation. Map annotations are small pieces of information tied to a particular location. Apple's Maps app usually represents them as little pins.
To create your annotations, you lot create a class that conforms to MKAnnotation
, add the annotation to the map and tell the map how the annotation should be displayed.
The Artwork Class
First, right-click the HonoluluArt binder in the Projection navigator and pick New File…. Choose Swift File and name your new file Artwork.swift.
Open Artwork.swift in the editor and add together the following below import Foundation
:
import MapKit class Artwork: NSObject, MKAnnotation { permit title: Cord? let locationName: String? let discipline: String? let coordinate: CLLocationCoordinate2D init( title: Cord?, locationName: String?, discipline: String?, coordinate: CLLocationCoordinate2D ) { self.title = title self.locationName = locationName self.discipline = bailiwick cocky.coordinate = coordinate super.init() } var subtitle: String? { return locationName } }
To arrange to MKAnnotation
, Artwork
must subclass NSObject
, because MKAnnotation
is an NSObjectProtocol
.
MKAnnotation
requires the coordinate
property. If you want your annotation view to display a title and subtitle when the user taps a marker, your class besides needs properties named title
and subtitle
.
Information technology's perfectly sensible for the Artwork
class to have stored properties named title
and coordinate
, but none of the PublicArt.geojson backdrop naturally map to the idea of subtitle. To arrange to MKAnnotation
, you brand subtitle
a computed holding that returns locationName
.
The MKAnnotation
protocol properties title
and subtitle
are defined as optional strings, simply yous may wonder why you've used String?
equally the type for the locationName
and discipline
properties. Since these properties are set from an external information source, the PublicArt.geojson file, you can't guarantee they'll always exist. Better to be safety.
OK, so you'll use the championship
, locationName
and coordinate
properties for the MKAnnotation
object, but what's the discipline
property for? You lot'll find out later in this tutorial! ;]
Adding an Annotation
Next, you'll add an Artwork
object to the map view for every artwork you lot want to plot. For now, you lot're calculation merely one artwork, and so switch to ViewController.swift and add together the following lines to the stop of viewDidLoad()
:
// Bear witness artwork on map let artwork = Artwork( championship: "King David Kalakaua", locationName: "Waikiki Gateway Park", subject: "Sculpture", coordinate: CLLocationCoordinate2D(latitude: 21.283921, longitude: -157.831661)) mapView.addAnnotation(artwork)
Here, you create a new Artwork
object and add information technology equally an annotation to the map view. MKMapView
as well provides addAnnotations(_:)
, which you'll use after in this tutorial when you take an array of annotations to add to the map view.
Build and run. Now you lot can come across that King David Kalakaua's statue is at the gateway to Waikiki!
The default annotation marking view shows the location with the championship below the marker. Select the mark. Information technology grows and now shows the subtitle, too:
Well, that's OK, but you've seen that tapping a marker in other apps shows a callout: a little, foursquare oral communication bubble. For that, you must configure the annotation view.
Configuring the Annotation View
1 way to configure the annotation view is to implement the map view's mapView(_:viewFor:)
delegate method. Your chore in this consul method is to render an instance of MKAnnotationView
to present every bit a visual indicator of the annotation.
In this case, ViewController
is the consul for the map view. To avert clutter and improve readability, you lot'll create an extension of ViewController
.
Add together the post-obit at the bottom of ViewController.swift:
extension ViewController: MKMapViewDelegate { // 1 func mapView( _ mapView: MKMapView, viewFor notation: MKAnnotation ) -> MKAnnotationView? { // 2 guard let annotation = annotation every bit? Artwork else { return aught } // 3 permit identifier = "artwork" var view: MKMarkerAnnotationView // 4 if let dequeuedView = mapView.dequeueReusableAnnotationView( withIdentifier: identifier) every bit? MKMarkerAnnotationView { dequeuedView.annotation = annotation view = dequeuedView } else { // 5 view = MKMarkerAnnotationView( notation: annotation, reuseIdentifier: identifier) view.canShowCallout = truthful view.calloutOffset = CGPoint(x: -5, y: 5) view.rightCalloutAccessoryView = UIButton(blazon: .detailDisclosure) } return view } }
Here's what you're doing:
-
mapView(_:viewFor:)
gets called for every note you add to the map — liketableView(_:cellForRowAt:)
when working with table views — to return the view for each note. - Your app might use other annotations, like user location, so check that this note is an
Artwork
object. If information technology isn't, returnnil
to let the map view apply its default notation view. - You create each view every bit an
MKMarkerAnnotationView
. Later in this tutorial, you'll createMKAnnotationView
objects to brandish images instead of markers. - Too similarly to
tableView(_:cellForRowAt:)
, a map view reuses annotation views that are no longer visible. And so yous check to see if a reusable notation view is available before creating a new ane. When you dequeue a reusable annotation, you give it an identifier.If you take multiple styles of annotations, be sure to have a unique identifier for each one. Over again, it'southward the aforementioned idea backside a cell identifier in
tableView(_:cellForRowAt:)
. - Here you create a new
MKMarkerAnnotationView
object if an annotation view could not be dequeued. It uses the title and subtitle properties of yourArtwork
class to determine what to testify in the callout.
The Map View Delegate
All that's left is setting ViewController
equally the consul of the map view. You can do this in Main.storyboard, only it's more visible if you lot do it in code. In ViewController.swift, add this line to viewDidLoad()
, before the statement that creates artwork
:
mapView.delegate = self
And that's it! Build and run. Tap the mark to pop upwardly the callout bubble:
mapView(_:viewFor:)
configures the callout to include a item disclosure info button on the right side, but tapping that push doesn't do annihilation yet. Yous could implement it to bear witness an warning with more info or to open up a particular view controller.
Here's a neat 3rd option. When the user taps the info push button, your app launches the Maps app, complete with driving, walking and transit directions to get from the simulated user location to the artwork!
Launching the Maps App
To provide this bully user experience, open Artwork.swift and add together this import
argument, below the other 2:
import Contacts
This adds the Contacts framework, which contains lexicon key constants such as CNPostalAddressStreetKey
, for when yous need to set the accost, city or land fields of a location.
To tell the Maps app where to go, you lot must laissez passer information technology an MKMapItem
. This form describes a betoken of interest on the map. To create i, you must first create an MKPlacemark
to depict the bespeak.
Next, add together the following belongings to the course:
var mapItem: MKMapItem? { guard let location = locationName else { render nil } let addressDict = [CNPostalAddressStreetKey: location] let placemark = MKPlacemark( coordinate: coordinate, addressDictionary: addressDict) allow mapItem = MKMapItem(placemark: placemark) mapItem.name = title return mapItem }
You employ your existing location information as the accost to create an MKPlacemark
. You then create and configure the MKMapItem
you lot need for communicating with Maps.
Handling the Callout
Adjacent, you have to tell MapKit what to do when the user taps the callout button. Open ViewController.swift, and add together this method to the MKMapViewDelegate
extension:
func mapView( _ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl ) { baby-sit let artwork = view.annotation as? Artwork else { return } let launchOptions = [ MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving ] artwork.mapItem?.openInMaps(launchOptions: launchOptions) }
When the user taps a map annotation marker, the callout shows an info button. If the user taps this info push button, iOS calls mapView(_:annotationView:calloutAccessoryControlTapped:)
.
In this method, you grab the Artwork
object this tap refers to, then launch Maps past creating an associated MKMapItem
and calling openInMaps(launchOptions:)
on the map item.
Notice you're passing a dictionary to this method. This allows you to specify a few different options. Here, the DirectionsModeKey
is set to Driving
.
This causes Maps to testify driving directions from the user's electric current location to this location. Neat!
Note: Explore the MKMapItem
documentation to see other launch option dictionary keys, and the openMaps(with:launchOptions:)
method that lets you laissez passer an array of MKMapItem
objects.
Setting Your Simulated Location
Earlier you build and run, you should movement to Honolulu. Well, just fix your simulated location to Honolulu.:]
In Xcode, go to Production ► Scheme ► Edit Scheme…, select Run from the left menu, then select the Options tab. Check Allow Location Simulation and select Honolulu, How-do-you-do, USA equally the Default Location. Then click the Shut button:
Build and run. You'll see the map zoom in on Waikiki, every bit before. Tap the marker, so tap the info button in the callout and watch it launch Maps to show the statue'due south location and driving directions to information technology:
This calls for a celebration with your favorite tropical drink!
Note: The first time you lot open Maps, information technology prompts you to allow Maps to access your location — tap Allow While Using App — and displays a Safety Warning.
Decoding GeoJSON with MKGeoJSONDecoder
Now that you lot know how to show one artwork on the map and how to launch Maps from the mark's callout info push button, information technology'southward time to parse the dataset into an array of Artwork
objects. Then you'll add them as annotations to the map view to display all artworks located in the current map region.
MapKit has MKGeoJSONDecoder
, a super-useful characteristic. It can decode GeoJSON data and render an assortment of objects that implement the MKGeoJSONObject
protocol. MapKit likewise provides i concrete course that implements this protocol: MKGeoJSONFeature
, which is all you'll need for this tutorial.
Add this failable initializer to Artwork.swift, below the initializer:
init?(feature: MKGeoJSONFeature) { // 1 baby-sit let point = feature.geometry.first every bit? MKPointAnnotation, let propertiesData = feature.properties, allow json = try? JSONSerialization.jsonObject(with: propertiesData), let properties = json as? [Cord: Any] else { return zip } // 3 title = properties["championship"] equally? String locationName = properties["location"] as? String bailiwick = properties["discipline"] as? Cord coordinate = point.coordinate super.init() }
Here's what you're doing:
-
MKGeoJSONFeature
has ageometry
property representing i or more shapes associated with the feature. All the features in PublicArt.geojson are signal locations and MapKit helpfully creates aMKPointAnnotation
for y'all. This is where y'all'll detect the coordinate every bit aCLLocationCoordinate2D
. - Next, you read the feature's
properties
, which is of typeData?
and contains a serialized JSON lexicon. You useJSONSerialization
to decode the data into a Swift dictionary. - At present that the properties are decoded, you can set the appropriate
Artwork
properties from the dictionary values.
Making Annotations
To apply this initializer, open ViewController.swift and add together the following property, an array to hold the Artwork
objects from the GeoJSON file, to the class:
private var artworks: [Artwork] = []
Next, add the following helper method to the class:
private func loadInitialData() { // 1 guard permit fileName = Parcel.main.url(forResource: "PublicArt", withExtension: "geojson"), let artworkData = effort? Data(contentsOf: fileName) else { render } do { // two let features = try MKGeoJSONDecoder() .decode(artworkData) .compactMap { $0 as? MKGeoJSONFeature } // 3 let validWorks = features.compactMap(Artwork.init) // iv artworks.suspend(contentsOf: validWorks) } grab { // v print("Unexpected error: \(error).") } }
Hither'south what you lot're doing in this code:
- To begin, you read PublicArt.geojson into a
Data
object. - You use
MKGeoJSONDecoder
to obtain an assortment of GeoJSON objects only but continue instances ofMKGeoJSONFeature
usingcompactMap
. - You transform the
MKGeoJSONFeature
objects intoArtwork
objects using its failable initializer you lot added andcompactMap
again. - You lot append the resulting
validWorks
to theartworks
array. - Considering
MKGeoJSONDecoder
'sdecode(_ :)
method canthrow
an error, you grab it and impress the error to the Xcode console.
Plotting the Artwork
You now have an array of all the public artwork in the dataset, which you'll add to the map.
Still in ViewController.swift, add the following code at the cease of viewDidLoad()
:
loadInitialData() mapView.addAnnotations(artworks)
Note: Be sure to use the plural addAnnotationsouthward
, non the singular addAnnotation
!
Delete the lines that create the single King David Kalakaua map annotation. You don't need them at present that loadInitialData()
creates the artworks
array.
Build and run. Cheque out all the markers!
Move the map around to see other markers appear. Tap a marker to open its callout bubble, and then tap its info button to launch the Maps. Yep, everything y'all did with the King Kalakaua statue works with all the new artwork as well!
If you're worried near adding annotations to the map when they're not visible, don't be! Apple recommends adding all the annotations right away, whether or not they're visible in the map region. When you motion the map, it automatically displays the visible annotations.
And that'south it! You lot've built an app that parses a GeoJSON file into an assortment of artworks, then displays them equally annotation markers, with a callout info push button that launches Maps. Gloat with a hula dance effectually your desk! :]
Just await, there are still a few bits of bling to add.
Customizing Annotations
Recall the discipline
property in the Artwork
form? Its values are things like Sculpture and Landscape. In fact, the most numerous disciplines are Sculpture, Plaque, Mural and Monument.
It'south easy to color-lawmaking the markers, so the nigh numerous disciplines each take their own colored marker, and all the other disciples accept green markers.
Markers with Color-Coding and Text
In Artwork.swift, add this holding:
var markerTintColor: UIColor { switch discipline { instance "Monument": return .red case "Mural": return .cyan instance "Plaque": return .blue instance "Sculpture": return .purple default: return .green } }
Now, yous could keep calculation code to mapView(_:viewFor:)
, simply that would clutter the view controller. There's a more than elegant way, similar to what y'all can do for tabular array view cells. Create a new Swift file named ArtworkViews.swift and add this lawmaking, beneath the import
statement:
import MapKit class ArtworkMarkerView: MKMarkerAnnotationView { override var annotation: MKAnnotation? { willSet { // 1 guard allow artwork = newValue every bit? Artwork else { return } canShowCallout = true calloutOffset = CGPoint(x: -five, y: five) rightCalloutAccessoryView = UIButton(type: .detailDisclosure) // 2 markerTintColor = artwork.markerTintColor if let letter = artwork.discipline?.first { glyphText = Cord(letter of the alphabet) } } } }
Soon, you'll register this class as a reusable annotation view for Artwork
annotations. The organization passes it an annotation as newValue
, and so here's what you're doing:
- These lines do the same matter as your
mapView(_:viewFor:)
, configuring the callout. - Then you ready the marker's tint color and as well supervene upon its pivot icon, or glyph, with the start letter of the alphabet of the notation's discipline.
Color My World
At present switch to ViewController.swift, and add this line to viewDidLoad()
, earlier calling loadInitialData()
:
mapView.register( ArtworkMarkerView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)
Here, y'all register your new class with the map view'southward default reuse identifier. For an app with more annotation types, you would register classes with custom identifiers.
Ringlet down to the extension and delete mapView(_:viewFor:)
.
Build and run. And then move the map around to see the different colored and labeled markers:
In this section of the map, there'southward much more than art than the map view shows. It reduces clutter by clustering markers that are too shut together. In the next department, yous'll see all the annotations.
Only starting time, fix the glyph's prototype instead of its text. Add the following property to Artwork.swift:
var paradigm: UIImage { baby-sit let proper noun = discipline else { render #imageLiteral(resourceName: "Flag") } switch name { example "Monument": return #imageLiteral(resourceName: "Monument") instance "Sculpture": return #imageLiteral(resourceName: "Sculpture") case "Plaque": return #imageLiteral(resourceName: "Plaque") case "Mural": return #imageLiteral(resourceName: "Landscape") default: render #imageLiteral(resourceName: "Flag") } }
These images from icons8.com are already in Assets.xcassets.
Then, in ArtworkViews.swift, replace the glyphText
lines with:
glyphImage = artwork.prototype
Build and run to run into unlike colored markers with images:
And that's a segue to some other customization option and your next task: Replace the markers with images!
Annotations with Images
In ArtworkViews.swift, add the post-obit form:
course ArtworkView: MKAnnotationView { override var annotation: MKAnnotation? { willSet { guard let artwork = newValue equally? Artwork else { return } canShowCallout = truthful calloutOffset = CGPoint(10: -5, y: v) rightCalloutAccessoryView = UIButton(type: .detailDisclosure) image = artwork.epitome } } }
At present, you're using a manifestly former MKAnnotationView
instead of an MKMarkerAnnotationView
, and the view has an image
property.
Back in ViewController.swift, in viewDidLoad()
, register this new grade, instead of ArtworkMarkerView
:
mapView.register( ArtworkView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)
Build and run to come across all the icons:
Custom Callout Accessory Views
The right callout accessory is an info push button, but tapping it opens Maps. So, now y'all'll modify the button to prove the Maps icon.
Find this line in ArtworkView
:
rightCalloutAccessoryView = UIButton(blazon: .detailDisclosure)
Supervene upon this line with the following lawmaking:
allow mapsButton = UIButton(frame: CGRect( origin: CGPoint.zero, size: CGSize(width: 48, height: 48))) mapsButton.setBackgroundImage(#imageLiteral(resourceName: "Map"), for: .normal) rightCalloutAccessoryView = mapsButton
Here, you lot create a UIButton
, set its background image to a map icon, also from icons8.com in Assets.xcassets, and so set the view's right callout accessory to this button.
Build and run. Then tap a view to see the new Maps push:
The final customization is the detail callout accessory. It'south a unmarried line, which is enough for brusk location text, just some of the longer location values are truncated like this i:
Now y'all need a multi-line characterization. Add the following code to ArtworkView
'southward willSet
:
permit detailLabel = UILabel() detailLabel.numberOfLines = 0 detailLabel.font = detailLabel.font.withSize(12) detailLabel.text = artwork.subtitle detailCalloutAccessoryView = detailLabel
Build and run. Then tap a view to see the long location text in full.
Where To Go From Here?
You tin can download the completed version of the project using the Download Materials push at the peak or lesser of this tutorial.
Now you lot know the nuts of using MapKit, only there's more yous tin can add together: map display customizations, geocoding, geofencing, custom map overlays, and more. Apple tree's MapKit documentation and Location and Maps Programming Guide are great places to detect more information.
Also await at WWDC 2019 Session 236: What's New in MapKit and MapKit JS, to detect more cool features added in iOS xiii.
At that place's also take a terrific video course, MapKit and Core Location, that covers many awesome topics.
Core Location Tutorial for iOS: Tracking Visited Locations explains how to track your location and display it using MapKit.
If y'all have any questions as you use MapKit in your apps, or tips for other MapKit users, delight join in the forum discussion below!
Source: https://www.raywenderlich.com/7738344-mapkit-tutorial-getting-started
Posted by: byaskentemad1984.blogspot.com
0 Response to "How To Create A Service Area Map"
Post a Comment