SwiftUI MapKit: How to display a map and show a location
14 May 2021
The MapKit framework is utilized to display a map or satellite imagery from your app’s very own interface. It can also be used to call out points of interest, and determine placemark information for coordinates on the map. We can use MapKit to load a map and center on a location!
Basic Code Sample
Setting up a map is pretty easy, the basic code is as simple as this:
However, notice that it needs a Binding or @State variable of type MKCoordinateRegion. In order to do so we need to look at the basic requirements for MKCoordinateRegion first.
The basic syntax is as follows:
MKCoordinateRegion(center: CLLocationCoordinate2D, span: MKCoordinateSpan)
it now needs to set up two new data types namely the CLLocationCoordinate2D and MKCoordinateSpan.
CLLocationCoordinate2D is simply the longitude and latitude of a specific coordinate of the map which can be done by simply doing it like this
CLLocationCoordinate2D( latitude: 37.789467, longitude:-122.416772 )
MKCoordinateSpan is the width and height of the map view in degrees, namely the latitudeDelta and longitudeDelta.
The range of values for latitude is from -90 to 90 and -180 to 180 for longitude. Thus, setting a high value for this makes the view wider view (zoomed out) while setting a smaller value for this makes it more precise view (zoomed in). Ideally, a good zoomed in view is around 0.1 to 0.5 degree while a nice zoomed out view is around 1 to 10 degrees.
MKCoordinateSpan( latitudeDelta: 0.5, longitudeDelta: 0.5 )
Given both this information, we can now easily create our MKCoordinateRegion by doing this:
@State var region = MKCoordinateRegion( center: CLLocationCoordinate2D( latitude: 37.789467, longitude:-122.416772 ), span: MKCoordinateSpan( latitudeDelta: 0.5, longitudeDelta: 0.5 ) )
Now why does it need to be a Binding variable? well in normal circumstances the location set might change or the user might want to zoom in/out or pan around the map so in order handle this the state needs to change on the fly.
Finally, we can use this MKCoordinateRegion to feed our Map and display it easily.
Although it is enough to display a map using the basic Map declaration with just the coordinateRegion it will just look like a basic map centered around the location that you specified, it won’t even have a marker on where you are!
Here is where some map options or map overloads come in, ideally you want to use a map with this lists of overloads:
Map(coordinateRegion: Binding<MKCoordinateRegion>, interactionModes: MapInteractionModes, showsUserLocation: Bool, userTrackingMode: Binding<MapUserTrackingMode?)
interactionModes is basically how you want to interact with your map, you can fill this up easily by using the built-in class called MapInteractionModes and doing a .pan or .zoom if you want only specific interactions enabled, or you can allow both but doing a .all
showsUserLocation just asked for a Bool if you want to show the location, if activated it will show a marker for the location of the user.
userTrackingMode is basically if you want to track the movement or changes in the location, you can set this up easily by using the built-in class called MapUserTrackingMode and doing a .follow or .none
However it is to be to be noted that userTrackingMode should be a Binding variable so its ideal. to set it separately then using the variable for your Map set-up later on.
@State var tracking:MapUserTrackingMode = .follow
Given all this info we can now set our Map with more specific functionalities and control.
Map( coordinateRegion: $region, interactionModes: MapInteractionModes.all, showsUserLocation: true, userTrackingMode: $tracking )
Note: Since we didn’t set-up the location of the user it wont show a marker in our map at all because we only set a location for the region