NEW: Start my new Ultimate Portfolio App course with a free Hacking with Swift+ trial! >>

How to show annotations in a Map view

Paul Hudson    @twostraws   

Updated for Xcode 12.5

New in iOS 14

SwiftUI’s Map view allows us to show annotation views on top of the map, including default markers and pins, as well as completely custom views.

This takes three steps:

  1. Create some sort of state that will track the coordinates being shown by the map, using MKCoordinateRegion to track the center and zoom level of the map.
  2. Prepare an array of location to use for your annotations.
  3. Decide how you want them to be shown on your map. There are built-in MapPin and MapMarker annotations you can show, or you can use your own views.

Whatever array of locations you have, the types you’re using must conform to Identifiable so SwiftUI understands how to identify each item uniquely. For example, you might use something like this:

struct Location: Identifiable {
    let id = UUID()
    let name: String
    let coordinate: CLLocationCoordinate2D
}

If all you have is CLLocationCoordinate2D data, you can use them directly by adding an extension such as this one:

extension CLLocationCoordinate2D: Identifiable {
    public var id: String {
        "\(latitude)-\(longitude)"
    }
}

Anyway, here’s an example that puts everything together so you can see map pins over various capital cities:

struct Location: Identifiable {
    let id = UUID()
    let name: String
    let coordinate: CLLocationCoordinate2D
}

struct ContentView: View {
    @State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 51.507222, longitude: -0.1275), span: MKCoordinateSpan(latitudeDelta: 10, longitudeDelta: 10))

    let annotations = [
        Location(name: "London", coordinate: CLLocationCoordinate2D(latitude: 51.507222, longitude: -0.1275)),
        Location(name: "Paris", coordinate: CLLocationCoordinate2D(latitude: 48.8567, longitude: 2.3508)),
        Location(name: "Rome", coordinate: CLLocationCoordinate2D(latitude: 41.9, longitude: 12.5)),
        Location(name: "Washington DC", coordinate: CLLocationCoordinate2D(latitude: 38.895111, longitude: -77.036667))
    ]

    var body: some View {
        Map(coordinateRegion: $region, annotationItems: annotations) {
            MapPin(coordinate: $0.coordinate)
        }
    }
}

That uses the traditional pin style that iOS has had for years, but if you want the larger pin style you can use MapMarker instead, like this:

Map(coordinateRegion: $region, annotationItems: annotations) {
    MapMarker(coordinate: $0.coordinate)
}

And if you want complete control, you can also pass in completely custom views – some text, an image, a NavigationLink, and so on.

For example, we could draw a 4-point stroked circle over our capital cities like this:

MapAnnotation(coordinate: $0.coordinate) {
    Circle()
        .strokeBorder(Color.red, lineWidth: 4)
        .frame(width: 40, height: 40)
}
Hacking with Swift is sponsored by Emerge

SPONSORED Emerge helps iOS devs write better, smaller apps by profiling binary size on each pull request and surfacing insights and suggestions. Companies using Emerge have reduced the size of their apps by up to 50% in just the first day. Built by a team with years of experience reducing app size at Airbnb.

Set up a demo!

Sponsor Hacking with Swift and reach the world's largest Swift community!

Similar solutions…

BUY OUR BOOKS
Buy Pro Swift Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift (Vapor Edition) Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Server-Side Swift (Kitura Edition) Buy Beyond Code

Was this page useful? Let us know!

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.