MapKit is a strong framework that permits builders so as to add maps, annotations, and location-based options to their iOS purposes. With SwiftUI, you may simply combine MapKit into your app and create interactive and dynamic maps that provide an awesome person expertise. On this tutorial, we are going to discover tips on how to work with maps and annotations in SwiftUI, and tips on how to customise the map type and digicam place.
The MapKit Fundamentals
Let’s begin with the fundamentals of MapKit. The MapKit framework features a Map
view that builders can use to embed a map in any SwiftUI venture. Right here is an instance:
struct ContentView: View {
var physique: some View {
Map()
}
}
import SwiftUI import MapKit  struct ContentView: View { var physique: some View { Map() } } |
Earlier than utilizing the Map
view, it’s important to import the MapKit
framework. Then, to create a map, merely instantiate a Map
view. If you happen to’ve opened the Preview canvas in Xcode, it’s best to see a full display screen map within the simulator.
Altering the Preliminary Place with Map Digital camera
As a substitute of displaying a default location, the Map
view has one other init
methodology so that you can change the preliminary place of the map:
init( Â Â Â Â initialPosition: MapCameraPosition, Â Â Â Â bounds: MapCameraBounds? = nil, Â Â Â Â interactionModes: MapInteractionModes = .all, Â Â Â Â scope: Namespace.ID? = nil ) the place Content material == MapContentView<By no means, EmptyMapContent> |
You may an occasion of MapCameraPosition
because the preliminary place of the map. MapCameraPosition
accommodates varied properties that you should utilize to regulate which place or area is displayed, together with:
computerized
merchandise(MKMapItem)
– for displaying a selected map merchandise.area(MKCoordinateRegion)
– for displaying a selected area.rect(MKMapRect)
– for displaying particular map boundaries.digicam(MapCamera)
– for displaying an current digicam place.userLocation()
– for displaying the person’s location
As an illustration, you may instruct the map to show a selected area by utilizing .area(MKCoordinateRegion)
:
Map(initialPosition: .area(MKCoordinateRegion(heart: CLLocationCoordinate2D(latitude: 40.75773, longitude: –73.985708), span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)))) |
The coordinates within the above pattern is the GPS coordinates of Instances Sq. in New York. The worth of span
 is used to outline your required zoom degree of the map. The smaller the worth, the upper is the zoom degree.
When you’ve got a selected location for show, you may cross a map merchandise because the preliminary place. Here’s a pattern code snippet:
struct ContentView: View {
var physique: some View {
Map(initialPosition: .merchandise(MKMapItem(placemark: .init(coordinate: .bigBen))))
}
}
extension CLLocationCoordinate2D { Â Â Â Â static let bigBen = CLLocationCoordinate2D(latitude: 51.500685, longitude: –0.124570) } Â struct ContentView: View { Â Â Â Â Â var physique: some View { Â Â Â Â Â Â Â Â Map(initialPosition: .merchandise(MKMapItem(placemark: .init(coordinate: .bigBen)))) Â Â Â Â } } |
Animating the Change of Map Place
The Map
view additionally offers an extra init
methodology that accepts a binding to MapCameraPosition
. If it’s essential to change the place of the map, this init
methodology is extra applicable:
Map(place: $place) {
.
.
.
}
@State non-public var place: MapCameraPosition = .computerized  Map(place: $place) {   .   .   . } |
For instance, if you wish to add two buttons for customers to change between two places, you may write the code like this:
struct ContentView: View {
@State non-public var place: MapCameraPosition = .computerized
var physique: some View {
Map(place: $place)
.onAppear {
place = .merchandise(MKMapItem(placemark: .init(coordinate: .bigBen)))
}
.safeAreaInset(edge: .backside) {
HStack {
Button(motion: {
withAnimation {
place = .merchandise(MKMapItem(placemark: .init(coordinate: .bigBen)))
}
}) {
Textual content(“Huge Ben”)
}
.tint(.black)
.buttonStyle(.borderedProminent)
Button(motion: {
withAnimation {
place = .merchandise(MKMapItem(placemark: .init(coordinate: .towerBridge)))
}
}) {
Textual content(“Tower Bridge”)
}
.tint(.black)
.buttonStyle(.borderedProminent)
}
}
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
extension CLLocationCoordinate2D {     static let bigBen = CLLocationCoordinate2D(latitude: 51.500685, longitude: –0.124570)     static let towerBridge = CLLocationCoordinate2D(latitude: 51.505507, longitude: –0.075402) }  struct ContentView: View {      @State non-public var place: MapCameraPosition = .computerized      var physique: some View {         Map(place: $place)             .onAppear {                 place = .merchandise(MKMapItem(placemark: .init(coordinate: .bigBen)))             }             .safeAreaInset(edge: .backside) {                 HStack {                     Button(motion: {                         withAnimation {                             place = .merchandise(MKMapItem(placemark: .init(coordinate: .bigBen)))                         }                     }) {                         Textual content(“Huge Ben”)                     }                     .tint(.black)                     .buttonStyle(.borderedProminent)                      Button(motion: {                         withAnimation {                             place = .merchandise(MKMapItem(placemark: .init(coordinate: .towerBridge)))                         }                     }) {                         Textual content(“Tower Bridge”)                     }                     .tint(.black)                     .buttonStyle(.borderedProminent)                 }             }        } } |
By wrapping the place
variable with withAnimation
, the map view will mechanically animate the place change.
This animation works even higher while you present a MapCamera
with a pitch angle to create a 3D perspective. To see what occurs, you may attempt altering the place of Huge Ben within the following line of code:
place = .digicam(MapCamera( Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â centerCoordinate: .bigBen, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â distance: 800, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â heading: 90, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â pitch: 50)) |
Whenever you preview the map view, the digicam angle adjusts to indicate a 3D perspective of the area.
Including Markers and Annotations
Markers are a helpful characteristic in MapKit that mean you can show content material at a selected coordinate on the map. It provides an additional layer of data to your map, resembling a retailer or a restaurant. Markers will be custom-made with a system picture and tint colour, making them visually distinct and straightforward to acknowledge. Whether or not you’re constructing a navigation app or a journey information, markers are a invaluable instrument that may provide help to create a greater person expertise.
So as to add a marker, you may create the Marker
view within the map content material builder closure like this:
Map(place: $place) { Â Â Â Â Marker(“Pickup right here”, coordinate: .pickupLocation) } |
Optionally, you may customise the Marker
object with a system picture. To vary the colour of the marker, use the tint
modifier:
Marker(“Pickup right here”, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â systemImage: “automobile.entrance.waves.up”, Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â coordinate: .pickupLocation) Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â .tint(.purple) |
Along with Marker
, SwiftUI now contains an Annotation
view in iOS 17 for indicating a location on a map. It capabilities equally to Marker
, however provides better flexibility for personalization.
So as to add an annotation, you create an Annotation
view within the map content material closure. Here’s a pattern code snippet for including a easy annotation:
Map(place: $place) { Â Â Â Â Annotation(“Decide up”, coordinate: .pickupLocation, anchor: .backside) { Â Â Â Â Â Â Â Â Picture(systemName: “automobile.entrance.waves.up”) Â Â Â Â } } |
You could have the flexibleness to customise the annotation in a wide range of methods. By attaching totally different modifiers to it, you may change its look and habits. Moreover, you should utilize stack views to rearrange the totally different parts of the annotation and create a format that fits your wants. Right here is an instance:
Picture(systemName: “automobile.entrance.waves.up”)
.symbolEffect(.variableColor)
.padding()
.foregroundStyle(.white)
.background(Coloration.indigo)
.clipShape(Circle())
}
}
Annotation(“Decide up”, coordinate: .pickupLocation, anchor: .backside) { Â Â Â Â ZStack { Â Â Â Â Â Â Â Â Circle() Â Â Â Â Â Â Â Â Â Â Â Â .foregroundStyle(.indigo.opacity(0.5)) Â Â Â Â Â Â Â Â Â Â Â Â .body(width: 80, top: 80) Â Â Â Â Â Â Â Â Â Picture(systemName: “automobile.entrance.waves.up”) Â Â Â Â Â Â Â Â Â Â Â Â .symbolEffect(.variableColor) Â Â Â Â Â Â Â Â Â Â Â Â .padding() Â Â Â Â Â Â Â Â Â Â Â Â .foregroundStyle(.white) Â Â Â Â Â Â Â Â Â Â Â Â .background(Coloration.indigo) Â Â Â Â Â Â Â Â Â Â Â Â .clipShape(Circle()) Â Â Â Â } } |
This outcomes an animated annotation as proven within the beneath illustration.
Altering the Map Fashion
By default, the map view renders the map in a typical type. Nonetheless, you may change the type by utilizing the mapStyle
modifier:
}
.mapStyle(.imagery(elevation: .life like))
Map { Â } .mapStyle(.imagery(elevation: .life like)) |
This creates a map type primarily based on satellite tv for pc imagery. By specifying a life like
elevation, the map view renders a 3D map with a sensible look.
Optionally, you can too change the map type to hybrid like this:
Abstract
This tutorial covers tips on how to work with maps and annotations in SwiftUI, utilizing the MapKit framework. The most recent model of SwiftUI provides further APIs and views for builders to additional customise the map view. By now, it’s best to know tips on how to embed a map in your app and add an annotation to focus on a location on the map.
If you wish to be taught extra about SwiftUI, don’t neglect to take a look at our Mastering SwiftUI guide.