Introduction to MapKit for SwiftUI

SwiftUI is a very vast collection of features designed by Apple to make iOS development…swift-er. One of those handy features is it’s ability to make maps, specifically with MapKit.

Requirements: To use these MapKit features, you need to use Xcode 15 and later.

Table of contents

What is MapKit?

Creating a map

Markers

Annotations

Camera Position

Additional Resources

What is MapKit?

MapKit is one of Apple’s API frameworks that allows iOS developers to build map-centered views and apps easily and efficiently.

Based on the Apple documentation, MapKit can:

Creating a Map

Let’s start with a basic map.

To create a basic map, you first need to import MapKit into your Swift file. Then simply call Map() in the view.

import SwiftUI
import MapKit

struct MapContentView: View {
    var body: some View {       
            Map()
    }
}

#Preview {
    MapContentView()
}

Congratulations, you made a map! As you can tell this is just the bare bones. Now that you have a map, you have to customize it to fit your needs.

Customizing your map

Map Style

MapKit provides a couple of different map styles, such as standard, imagery, and hybrid.

Standard

The standard style is the default and can be seen in the map we just made. It marks most roads and road names, as well as location markings. Essentially a mini Apple Maps without functionality.

Imagery

The imagery style provides a rendered satellite view map. Unlike standard, on imagery, roads and locations are not marked.

import SwiftUI
import MapKit

struct MapContentView: View {
    var body: some View {       
            Map().mapStyle(.imagery)
    }
}

#Preview {
    MapContentView()
}

Hybrid

Want rendered satellite view and road/location names? Then the hybrid style is for you! Hybrid combines the view of imagery and the road/location naming of standard, hence the name hybrid.

import SwiftUI
import MapKit

struct MapContentView: View {
    var body: some View {       
            Map().mapStyle(.hybrid)
    }
}

#Preview {
    MapContentView()
}

Additional Map Style Features

You can also add some additional features to the styles:

For more information, visit Apple documentation for Map Styles.

Markers

Now that we have a general map, let’s add Markers. In MapKit, markers are a balloon-shaped annotation that marks a location based on a set of coordinates.

To create a marker, start with a CLLocationCoordinate2D object to represent your coordinate. Then, add it to your Map’s contents through the Marker() class. The example below hardcodes a coordinate for Robarts Library but it still takes the same approach if you want to set a coordinate dynamically.

  import SwiftUI
  import MapKit
    
  struct MapContentView: View {
    let robarts = CLLocationCoordinate2D(latitude: 43.664486, longitude: -79.399689)
    var body: some View {
        Map(){
          Marker("Robarts", coordinate: robarts)
        }
     }
  }
   
  #Preview {
       MapContentView()
  }

Marker Customization

There are a couple of ways to customize your marker, such as color and what is displayed in the marker bubble.

Color

To change the color of your marker you can apply the .tint() method. Tint takes in a Color object so you can either do a system color such as .blue or your own custom color.

     Marker("Robarts", coordinate: robarts).tint(.blue)

Icon

To change what is displayed in the Marker bubble you can add the systemImage, image, or monogram parameters to your Marker as shown below.

System Image:

     Marker("Bahen", systemImage: "star.fill", coordinate: bahen)

Image:

     Marker("Robarts", image: "<Your Image Name>", coordinate: robarts)

Monogram

     Marker("University College", monogram: Text("UC"), coordinate: uc)

If you want more freedom with your designing map pins, try using Annotations instead.

Annotations

Annotations allow for MapKit developers to completely redesign the location coordinate indicators. Unlike markers which had a set amount of parameters and there was no way to escape the bubble, Annotations instead takes in a Swift UI View().

For example, here we made the annotation to just be a system image with padding rather than a marker bubble.

import SwiftUI
import MapKit

struct MapContentView: View {
    
    let robarts = CLLocationCoordinate2D(latitude: 43.664486, longitude: -79.399689)
    
    var body: some View {
        Map(){
            Annotation("Robarts", coordinate: robarts){
                Image(systemName: "books.vertical")
                    .padding(6)
                    .foregroundColor(.white)
                    .background(.blue)
            }
        }
    }
}

#Preview {
    MapContentView()
}

Overall, the annotations allow you to make the map pins completely your own. The possibilities are endless.

Camera Position

By default the map focuses on the map contents (markers, annotations, etc). To focus on a particular region or location, we can use MapCameraPosition. This can be helpful in a couple cases such as:

The default of the MapCameraPosition is known as .automatic. It will focus on the content of the map. The map without a camera position already does this, but .automatic could be helpful to update the camera position back to its original state when zooming in/out too much or when you jump between different camera positions.

@State private var cameraPosition: MapCameraPosition = .automatic

An example of using MapCameraPosition to focus on a location is setting .region. In the example below, we focus the map on the CN Tower even though the marker is at Robarts.

import SwiftUI
import MapKit

struct MapContentView: View {
    let robarts = CLLocationCoordinate2D(latitude: 43.664486, longitude: -79.399689)
    @State private var cameraPosition: MapCameraPosition = .region(MKCoordinateRegion(
        center: .init(latitude: 43.6426, longitude: -79.3871),
        span: .init(latitudeDelta: 0.01, longitudeDelta: 0.01))
    )

    
    var body: some View {
        Map(position: $cameraPosition){
            Marker("Robarts", coordinate: robarts)
            
        }
    }
}

#Preview {
    MapContentView()
}

Beyond these introductory examples, MapCameraPosition has a big potential and is very useful when creating dynamic maps.

Additional Resources

MapKit for SwiftUI is very large and has a lot of possible implementations, so this tutorial was just the tip of the iceberg! Below are some additional resources that could help with your MapKit journey.

How to…

For general information, refer to the Apple MapKit Documentation. It is very helpful, but a bit difficult to navigate.