Skip to content

Latest commit

 

History

History
265 lines (199 loc) · 9.61 KB

File metadata and controls

265 lines (199 loc) · 9.61 KB

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?

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:

  • Embed maps directly into your app’s windows and views.
  • Add annotations and overlays to a map to call out points of interest.
  • Add LookAround capabilities to enable users to explore locations at street level.
  • Respond to user interactions with well known points of interest, geographical features, and boundaries.
  • Provide text completion for search bars to make it easy for users to search for a destination or point of interest.

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:

  • elevation (hybrid/standard): whether the maps render elevation
  • showsTraffic (hybrid/standard) : whether the map can display traffic
  • pointsOfInterest (hybrid/standard) : a collection of certain PointOfInterestCategories objects for the map to show
  • emphasis (standard) : dictates how the app emphasizes certain features

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:

  • When you finish searching for a specific location, focus the map on that location
  • Focus the map on the location of the user
  • If the user presses a certain button, change map focus

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.