How to use MapKit, the new map framework in SwiftUI

Insert image description here

Insert image description here

Preface

After understanding MapKit in iOS 17, we will find that Apple has introduced an API that is more suitable for SwiftUI.

MapKit deprecations

Once you update your app target to iOS 17, Xcode will mark any usage of the old Map initializer as deprecated:

There will be a warning: init coordinate region has been deprecated in iOS 17. Use a map initializer with a MapContentBuilder parameter instead.

In iOS 17, MapKit introduces map initializers for SwiftUI that require MapContentBuilder parameters. Let me introduce you to the basic knowledge related to MapKit.

MapContentBuilder(iOS 17)

In iOS 17, various initializers for map views require a content parameter named MapContentBuilder. MapContentBuilder is a result builder that allows adding map content such as markers, annotations, and custom content in closures.

Let's see how it works, here are the coordinates of some London landmarks:

extension CLLocationCoordinate2D {
    
    
  static let towerBridge = CLLocationCoordinate2D(latitude: 51.5055, longitude: -0.075406)
  static let boe = CLLocationCoordinate2D(latitude: 51.5142, longitude: -0.0885)
  static let hydepark = CLLocationCoordinate2D(latitude: 51.508611, longitude: -0.163611)
  static let kingsCross = CLLocationCoordinate2D(latitude: 51.5309, longitude: -0.1233)
}

To create a map view with markers and annotations, the detailed code is as follows:

struct ContentView: View {
    
    
  var body: some View {
    
    
    Map {
    
    
      Marker("Tower Bridge", coordinate: .towerBridge)
      Marker("Hyde Park", coordinate: .hydepark)
      Marker("Bank of England", 
        systemImage: "sterlingsign", coordinate: .boe)
        .tint(.green)
    
      Annotation("Kings Cross", 
        coordinate: .kingsCross, anchor: .bottom) {
    
    
          VStack {
    
    
              Text("在此搭乘火车!")
              Image(systemName: "train.side.front.car")
          }
          .foregroundColor(.blue)
          .padding()
          .background(in: .capsule)
      }
    }
  }
}

Without other options, the map view's bounds will surround the map content.

Map interaction

To control how users interact with the map, you can pass a set of allowed modes. All modes (pan, zoom, tilt, rotate) are allowed by default, the code is as follows:

Map(interactionModes: [.pan,.pitch]) {
    
     ... }

map style

Use the Map Style view modifier to switch between standard, satellite or hybrid styles, control height, show points of interest and show traffic conditions, the code is as follows:

Map {
    
     ...
}
.mapStyle(.hybrid(elevation: .realistic,
  pointsOfInterest: .including([.publicTransport]), 
  showsTraffic: true))

map control

Standard map controls such as compass, user position, tilt, scale, and zoom controls are implemented as SwiftUI views. This means they can be placed anywhere in the view, but a map-scoped namespace needs to be defined to associate them with the map they control, as shown below:

struct ContentView: View {
    
    
  @Namespace var mapScope

  var body: some View {
    
    
    VStack {
    
    
      Map(scope: mapScope) {
    
     ... }
      MapCompass(scope: mapScope)
    }
    .mapScope(mapScope)
  }
}

To place them in standard locations, use the map control view modifier, as follows:

Map {
    
     ...
}
.mapControls {
    
    
  MapPitchToggle()
  MapUserLocationButton()
  MapCompass()
}

map camera location

The map camera position defines the virtual position from which the map is viewed from above the map surface. You can use an existing feature, map boundary, region, or user location to create a map camera position and set the initial map position with the following code:

Map(initialPosition: position)

Pass the binding of MapCameraPosition to the map so that it tracks the camera position as the user moves around the map, the code is as follows:

struct ContentView: View {
    
    
  @State private var position: MapCameraPosition = .region(.uk)

  var body: some View {
    
    
    Map(position: $position) {
    
    
      Marker("Tower Bridge", coordinate: .towerBridge)
    }
  }
}

Setting the location causes the map to change its camera position to match. For example, after the user moves the location, you want to add a button in the toolbar to reset the map to the original location, the code is as follows:

Map(position: $position) {
    
     ...
}
.toolbar {
    
    
  ToolbarItem {
    
    
    Button("重置") {
    
    
      position = .region(.uk)
    }
  }
}

Set the position to .automatic to frame the map content.

Summarize

That’s what you need to know to use MapKit in SwiftUI in iOS 17. With the introduction of MapContentBuilder and other new initializers, it's easier to create interactive map views, add markers, annotations, and custom content, and automatically update locations as the user moves the map camera.

Additionally, you can use Map Style modifiers and Map controls to customize the map's style and controls. These improvements make using MapKit in SwiftUI even more powerful and flexible.

Guess you like

Origin blog.csdn.net/qq_36478920/article/details/134219707
Recommended