1. Vorbereitung
In diesem Codelab lernen Sie, wie Sie das Maps SDK for iOS mit SwiftUI verwenden.
Vorbereitung
- Grundlegendes Swift-Wissen
- Grundkenntnisse in SwiftUI
Aufgaben
- Mithilfe von SwiftUI das Maps SDK for iOS aktivieren und verwenden, um Google Maps einer iOS-App hinzuzufügen
- Der Karte Markierungen hinzufügen
- Übergeben Sie den Status von einer SwiftUI-Ansicht an ein
GMSMapView
-Objekt und umgekehrt.
Voraussetzungen
- Xcode 11.0 oder höher
- Ein Google-Konto mit aktivierter Abrechnung
- Maps SDK for iOS
- Kardage
2. Einrichten
Aktivieren Sie für den folgenden Aktivierungsschritt das Maps SDK for iOS.
Google Maps Platform einrichten
Wenn Sie noch kein Google Cloud Platform-Konto und kein Projekt mit aktivierter Abrechnung haben, lesen Sie den Leitfaden Erste Schritte mit der Google Maps Platform, um ein Rechnungskonto und ein Projekt zu erstellen.
- Klicken Sie in der Cloud Console auf das Drop-down-Menü für Projekte und wählen Sie das Projekt aus, das Sie für dieses Codelab verwenden möchten.
- Aktivieren Sie im Google Cloud Marketplace die für dieses Codelab erforderlichen Google Maps Platform APIs und SDKs. Folgen Sie dazu der Anleitung in diesem Video oder dieser Dokumentation.
- Generieren Sie in der Cloud Console auf der Seite Anmeldedaten einen API-Schlüssel. Folgen Sie der Anleitung in diesem Video oder dieser Dokumentation. Für alle Anfragen an die Google Maps Platform ist ein API-Schlüssel erforderlich.
3. Startcode herunterladen
Damit Sie so schnell wie möglich loslegen können, erhalten Sie hier einen Startcode, den Sie bei diesem Codelab nutzen können. Sie können gerne direkt zur Lösung wechseln. Wenn Sie den Schritten aber selbst folgen möchten, lesen Sie einfach weiter.
- Wenn Sie
git
installiert haben, klonen Sie das Repository.
git clone https://github.com/googlecodelabs/maps-ios-swiftui.git
Alternativ können Sie auf die folgende Schaltfläche klicken, um den Quellcode herunterzuladen.
- Beim Abrufen des Codes befindet sich das Terminal im Terminal
cd
in das Verzeichnisstarter/GoogleMapsSwiftUI
. - Führe das
carthage update --platform iOS
-Tool aus, um das Maps SDK for iOS herunterzuladen - Öffnen Sie schließlich die Datei
GoogleMapsSwiftUI.xcodeproj
in Xcode
4. Codeübersicht
Für das heruntergeladene Starter-Projekt wurden die folgenden Kurse bereitgestellt und implementiert:
AppDelegate
: DieUIApplicationDelegate
von der Anwendung Hier wird das Maps SDK for iOS initialisiert.City
: Eine Struktur, die eine Stadt darstellt. Sie enthält den Namen und die Koordinaten der Stadt.MapViewController
– ein einfaches UIKit-UIViewController
-Objekt mit einer Google Maps-Karte (GMSMapView)SceneDelegate
ist dieUIWindowSceneDelegate
-Anwendung, von derContentView
instanziiert wird.
Außerdem werden in den folgenden Klassen nur teilweise Implementierungen ausgeführt und Sie werden bis zum Ende des Codelabs von Ihnen abgeschlossen:
ContentView
– Die SwiftUI-Ansicht der obersten Ebene, die Ihre App enthält.MapViewControllerBridge
: Eine Klasse, die eine UIKit-Ansicht in eine SwiftUI-Ansicht überbrückt. Insbesondere ist dies die Klasse, dieMapViewController
in SwiftUI zugänglich macht.
5. SwiftUI und UIKit im Vergleich
SwiftUI wurde in iOS 13 als alternatives UI-Framework über UIKit für die Entwicklung von iOS-Apps eingeführt. Verglichen mit der Vorgängerversion von UIKit bietet SwiftUI zahlreiche Vorteile. Hier einige Beispiele:
- Ansichten werden automatisch aktualisiert, wenn sich der Status ändert. Bei Objekten namens Status wird die Benutzeroberfläche automatisch aktualisiert, wenn der zugrunde liegende Wert geändert wird.
- Mit der Live-Vorschau lässt sich die Entwicklung beschleunigen. Durch Live-Vorschauen muss kein Code erstellt und bereitgestellt werden, da visuelle Änderungen nötig sind, um die SwiftUI-Vorschau in Xcode darzustellen.
- Die Informationsquelle lautet „Swift“. Alle Ansichten in SwiftUI werden in Swift deklariert, daher ist die Verwendung von Interface Builder nicht mehr erforderlich.
- Interoperabilität mit UIKit möglich. Dank der Interoperabilität mit UIKit können bestehende Apps SwiftUI weiterhin mit den bestehenden Ansichten nutzen. Außerdem können Bibliotheken, die SwiftUI noch nicht unterstützen, z. B. das Maps SDK for iOS, weiterhin in SwiftUI verwendet werden.
Einige Nachteile:
- SwiftUI ist nur auf iOS 13 und höher verfügbar.
- Die Ansichtshierarchie kann in Xcode-Vorschauen nicht untersucht werden.
SwiftUI-Status und Datenfluss
SwiftUI bietet eine neue Möglichkeit, eine deklarative Herangehensweise zu erstellen. Sie teilen SwiftUI mit, wie Ihre Ansicht zusammen mit den verschiedenen Status dargestellt werden soll. Das System erledigt den Rest. SwiftUI aktualisiert die Ansicht immer dann, wenn sich der zugrunde liegende Status aufgrund eines Ereignisses oder einer Nutzeraktion ändert. Diese Methode wird allgemein als unidirektionaler Datenfluss bezeichnet. Die Details dieses Designs werden in diesem Codelab nicht behandelt. Wir empfehlen Ihnen jedoch, den Abschnitt State and Data Flow in der Dokumentation von Apple durchzulesen.
UIKit und SwiftUI über UIViewRepresentable oder UIViewControllerRepresentable verbinden
Da das Maps SDK for iOS auf einer Benutzeroberfläche (UIKit) basiert, bietet es noch keine mit SwiftUI kompatible Ansicht, sodass sie in SwiftUI verwendet werden kann (entspricht UIViewRepresentable
oder UIViewControllerRepresentable
). Diese Protokolle ermöglichen es SwiftUI, in UIKit erstellte UIView
s bzw. UIViewController
s einzubeziehen. Sie können Google-Karten über beide Protokolle einer SwiftUI-Ansicht hinzufügen. Im nächsten Schritt sehen wir uns jedoch an, wie ein UIViewControllerRepresentable
eine UIViewController
-Karte mit einer Karte enthält.
6. Karte hinzufügen
In diesem Abschnitt fügen Sie Google Maps einer SwiftUI-Ansicht hinzu.
Eigenen API-Schlüssel hinzufügen
Der API-Schlüssel, den Sie in einem vorherigen Schritt erstellt haben, muss an das Maps SDK for iOS gesendet werden, um Ihr Konto mit der Karte zu verknüpfen, die in der App angezeigt wird.
Öffnen Sie die Datei AppDelegate.swift
und rufen Sie die Methode application(_, didFinishLaunchingWithOptions)
auf, um Ihren API-Schlüssel anzugeben. Derzeit wird das SDK über GMSServices.provideAPIKey()
mit dem String {YOUR_API_KEY" initialisiert. Ersetzen Sie diesen String durch Ihren API-Schlüssel. Wenn Sie diesen Schritt abschließen, wird das Maps SDK for iOS beim Start der App initialisiert.
Google Maps-Karte mit MapViewControllerBridge hinzufügen
Nachdem dein API-Schlüssel an das SDK übermittelt wurde, kannst du die Karte in der App aufrufen.
Der Ansichts-Controller, der im Starter-Code enthalten ist, enthält MapViewController
derzeit eine GMSMapView
Ansicht. Weil dieser Ansichts-Controller jedoch in UIKit erstellt wurde, müssen Sie diesen Kurs mit SwiftUI überbrücken, damit er in ContentView
verwendet werden kann. Gehe dazu folgendermaßen vor:
- Öffne die Datei
MapViewControllerBridge
in Xcode.
Diese Klasse entspricht UIViewControllerRepresentable, dem Protokoll, das zum Wrapping von UIKit UIViewController
erforderlich ist, damit es als SwiftUI-Ansicht verwendet werden kann. Mit anderen Worten: Wenn Sie dieses Protokoll einhalten, können Sie eine UIKit-Ansicht mit einer SwiftUI-Datenansicht verbinden. Die Einhaltung dieses Protokolls erfordert die Implementierung von zwei Methoden:
makeUIViewController(context)
: Diese Methode wird von SwiftUI aufgerufen, um die zugrunde liegendenUIViewController
zu erstellen. Hier würden Sie IhreUIViewController
instanziieren und ihren Anfangszustand übergeben.updateUIViewController(_, context)
: Diese Methode wird von SwiftUI aufgerufen, wenn sich der Status ändert. Hier würden Sie Änderungen am zugrunde liegendenUIViewController
vornehmen, um auf die Statusänderung zu reagieren.
MapViewController
erstellen
Instanziiere in der Funktion makeUIViewController(context)
eine neue MapViewController
und gib sie als Ergebnis zurück. Anschließend sollte der MapViewControllerBridge
so aussehen:
MapViewControllerBridge
import GoogleMaps
import SwiftUI
struct MapViewControllerBridge: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> MapViewController {
return MapViewController()
}
func updateUIViewController(_ uiViewController: MapViewController, context: Context) {
}
}
MapViewControllerBridge in ContentView verwenden
Nachdem MapViewControllerBridge
eine Instanz von MapViewController
erstellt hat, verwenden Sie als Nächstes diese Struktur in ContentView
, um eine Karte anzuzeigen.
- Öffne die Datei
ContentView
in Xcode.
ContentView
wird in SceneDelegate
instanziiert und enthält die Anwendungsansicht der obersten Ebene. Die Karte wird aus dieser Datei hinzugefügt.
- Erstelle eine
MapViewControllerBridge
in derbody
-Property.
In der body
-Property dieser Datei wurde bereits ein ZStack
-Element für Sie bereitgestellt und implementiert. Die ZStack
enthält derzeit eine Liste von Städten, die interaktiv sind und dragbar sind, die Sie in einem späteren Schritt verwenden. Erstelle derzeit innerhalb der ZStack
ein MapViewControllerBridge
als erste untergeordnete Ansicht des ZStack
, sodass eine Karte in der App hinter der Liste der Städte angezeigt wird. Danach sollte der Inhalt der body
-Property in ContentView
so aussehen:
Contentansicht
var body: some View {
let scrollViewHeight: CGFloat = 80
GeometryReader { geometry in
ZStack(alignment: .top) {
// Map
MapViewControllerBridge()
// Cities List
CitiesList(markers: $markers) { (marker) in
guard self.selectedMarker != marker else { return }
self.selectedMarker = marker
self.zoomInCenter = false
self.expandList = false
} handleAction: {
self.expandList.toggle()
} // ...
}
}
}
- Jetzt kannst du die App ausführen. Du solltest jetzt den Kartenaufruf auf deinem Bildschirm sowie eine dragbare Liste von Städten am unteren Bildschirmrand sehen.
7. Der Karte Markierungen hinzufügen
Im vorigen Schritt haben Sie neben einer interaktiven Liste eine Karte mit einer Liste von Städten hinzugefügt. In diesem Abschnitt fügen Sie für jede Stadt in der Liste Markierungen hinzu.
Markierungen als Bundesland
ContentView
deklariert derzeit eine Property namens markers
. Das ist eine Liste von GMSMarker
für jede Stadt, die in der statischen Property cities
angegeben wurde. Diese Property ist mit dem Status der SwiftUI-Property-Anmerkung versehen, um anzugeben, dass sie von SwiftUI verwaltet werden soll. Werden Änderungen mit dieser Eigenschaft erkannt, z. B. das Hinzufügen oder Entfernen einer Markierung, werden Datenansichten mit diesem Status aktualisiert.
Contentansicht
static let cities = [
City(name: "San Francisco", coordinate: CLLocationCoordinate2D(latitude: 37.7576, longitude: -122.4194)),
City(name: "Seattle", coordinate: CLLocationCoordinate2D(latitude: 47.6131742, longitude: -122.4824903)),
City(name: "Singapore", coordinate: CLLocationCoordinate2D(latitude: 1.3440852, longitude: 103.6836164)),
City(name: "Sydney", coordinate: CLLocationCoordinate2D(latitude: -33.8473552, longitude: 150.6511076)),
City(name: "Tokyo", coordinate: CLLocationCoordinate2D(latitude: 35.6684411, longitude: 139.6004407))
]
/// State for markers displayed on the map for each city in `cities`
@State var markers: [GMSMarker] = cities.map {
let marker = GMSMarker(position: $0.coordinate)
marker.title = $0.name
return marker
}
Beachten Sie, dass ContentView
die Property markers
verwendet, um die Liste der Städte zu rendern und sie an die Klasse CitiesList
zu übergeben.
Städteliste
struct CitiesList: View {
@Binding var markers: [GMSMarker]
var body: some View {
GeometryReader { geometry in
VStack(spacing: 0) {
// ...
// List of Cities
List {
ForEach(0..<self.markers.count) { id in
let marker = self.markers[id]
Button(action: {
buttonAction(marker)
}) {
Text(marker.title ?? "")
}
}
}.frame(maxWidth: .infinity)
}
}
}
}
Status mithilfe von Bindung an MapViewControllerBridge übergeben
Zusätzlich zur Liste der Städte, für die Daten aus der markers
-Property angezeigt werden, muss diese Property an die Struktur MapViewControllerBridge
übergeben werden, damit sie auf der Karte angezeigt werden kann. Gehen Sie hierzu folgendermaßen vor:
- Deklariere eine neue
markers
-Property inMapViewControllerBridge
, die mit@Binding
annotiert ist
MapViewControllerBridge
struct MapViewControllerBridge: : UIViewControllerRepresentable {
@Binding var markers: [GMSMarker]
// ...
}
- Aktualisiere in
MapViewControllerBridge
die MethodeupdateUIViewController(_, context)
, um die Propertymarkers
zu verwenden
Wie im vorherigen Schritt erwähnt, wird updateUIViewController(_, context)
von SwiftUI aufgerufen, wenn sich der Status ändert. Mit dieser Methode, die die Karte aktualisiert werden soll, werden die Markierungen in markers
angezeigt. Dazu musst du für jede Markierung die map
-Property aktualisieren. Nach Abschluss dieses Schritts sollte MapViewControllerBridge
so aussehen:
import GoogleMaps
import SwiftUI
struct MapViewControllerBridge: UIViewControllerRepresentable {
@Binding var markers: [GMSMarker]
func makeUIViewController(context: Context) -> MapViewController {
return MapViewController()
}
func updateUIViewController(_ uiViewController: MapViewController, context: Context) {
// Update the map for each marker
markers.forEach { $0.map = uiViewController.map }
}
}
- Property
markers
vonContentView
anMapViewControllerBridge
übergeben
Da Sie in MapViewControllerBridge
eine neue Property hinzugefügt haben, muss der Wert für diese Property jetzt im Initialisierungsmodus für MapViewControllerBridge
übergeben werden. Wenn Sie versuchen, eine App zu erstellen, werden Sie feststellen, dass sie nicht kompiliert wird. Führen Sie eine Aktualisierung von ContentView
durch, wo MapViewControllerBridge
erstellt wird, und übergeben Sie die Property markers
folgendermaßen, um das Problem zu beheben:
struct ContentView: View {
// ...
var body: some View {
// ...
GeometryReader { geometry in
ZStack(alignment: .top) {
// Map
MapViewControllerBridge(markers: $markers)
// ...
}
}
}
}
Das Präfix $
wurde zur Übergabe von markers
an MapViewControllerBridge
verwendet, da eine gebundene Property erwartet wird. $
ist ein reserviertes Präfix für die Verwendung mit Swift-Property-Wrappern. Wenn sie auf einen Bundesstaat angewendet wird, wird eine Bindung zurückgegeben.
- Führe die App aus, um die Markierungen auf der Karte zu sehen.
8. Animiert zur ausgewählten Stadt
Im vorherigen Schritt haben Sie einer Karte Markierungen hinzugefügt, indem Sie den Status von einer SwiftUI-Ansicht in eine andere übergeben. In diesem Schritt werden Sie zu einer Stadt/Markierung animiert, nachdem Sie auf die Liste geklickt haben. Um die Animation auszuführen, reagieren Sie auf Änderungen eines Status, indem Sie die Kameraposition beim Ändern der Karte ändern. Weitere Informationen zum Konzept der Kamera finden Sie unter Kamera und Ansicht.
Karte zur ausgewählten Stadt animieren
So animieren Sie die Karte zu einer ausgewählten Stadt:
- Neue Bindung in
MapViewControllerBridge
definieren
ContentView
hat die Status-Property selectedMarker
, die auf null zugeschnitten ist und aktualisiert wird, sobald eine Stadt in der Liste ausgewählt wird. Dies wird von der CitiesList
-Datenansicht buttonAction
in ContentView
verarbeitet.
Contentansicht
CitiesList(markers: $markers) { (marker) in
guard self.selectedMarker != marker else { return }
self.selectedMarker = marker
// ...
}
Jedes Mal, wenn sich selectedMarker
ändert, sollte MapViewControllerBridge
mit dieser Statusänderung vertraut sein, damit die Karte zur ausgewählten Markierung animiert werden kann. Definieren Sie also eine neue Bindung in MapViewControllerBridge
vom Typ GMSMarker
und nennen Sie die Property selectedMarker
.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
@Binding var selectedMarker: GMSMarker?
}
MapViewControllerBridge
aktualisieren, um die Karte bei jeder Änderung vonselectedMarker
zu animieren
Sobald eine neue Bindung deklariert wurde, müssen Sie die Funktion updateUIViewController_, context)
von MapViewControllerBridge
aktualisieren, damit die Karte mit der ausgewählten Markierung animiert wird. Kopieren Sie dazu einfach den Code unten:
struct MapViewControllerBridge: UIViewControllerRepresentable {
@Binding var selectedMarker: GMSMarker?
func updateUIViewController(_ uiViewController: MapViewController, context: Context) {
markers.forEach { $0.map = uiViewController.map }
selectedMarker?.map = uiViewController.map
animateToSelectedMarker(viewController: uiViewController)
}
private func animateToSelectedMarker(viewController: MapViewController) {
guard let selectedMarker = selectedMarker else {
return
}
let map = viewController.map
if map.selectedMarker != selectedMarker {
map.selectedMarker = selectedMarker
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
map.animate(toZoom: kGMSMinZoomLevel)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
map.animate(with: GMSCameraUpdate.setTarget(selectedMarker.position))
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
map.animate(toZoom: 12)
})
}
}
}
}
}
Die Funktion animateToSelectedMarker(viewController)
führt eine Reihe von Kartenanimationen mithilfe der Funktion animate(with)
von GMSMapView
aus.
selectedMarker
vonContentView
anMapViewControllerBridge
weitergeben
Sobald MapViewControllerBridge
die neue Bindung deklariert hat, aktualisieren Sie ContentView
, um die selectedMarker
zu übergeben, in der MapViewControllerBridge
instanziiert wird.
Contentansicht
struct ContentView: View {
// ...
var body: some View {
// ...
GeometryReader { geometry in
ZStack(alignment: .top) {
// Map
MapViewControllerBridge(markers: $markers, selectedMarker: $selectedMarker)
// ...
}
}
}
}
Wenn Sie diesen Schritt abschließen, wird die Karte jetzt animiert, wenn eine neue Stadt in der Liste ausgewählt wird.
SwiftUI-Ansicht zur Hervorhebung der Stadt animieren
Die Animation von Ansichten mit SwiftUI ist sehr einfach, da sie Animationen für Statusübergänge verarbeitet. Um dies zu zeigen, fügen Sie weitere Animationen hinzu, indem Sie die Ansicht auf die ausgewählte Stadt ausrichten, nachdem die Kartenanimation abgeschlossen ist. Das funktioniert so:
MapViewControllerBridge
eineonAnimationEnded
-Sperrung hinzufügen
Da die SwiftUI-Animation nach der zuvor hinzugefügten Kartenanimationssequenz ausgeführt wird, muss eine neue Schließung mit dem Namen onAnimationEnded
innerhalb von MapViewControllerBridge
deklariert und anschließend mit einer Verzögerung von 0,5 Sekunden nach der letzten Kartenanimation in der animateToSelectedMarker(viewController)
-Methode aufgerufen werden.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
var onAnimationEnded: () -> ()
private func animateToSelectedMarker(viewController: MapViewController) {
guard let selectedMarker = selectedMarker else {
return
}
let map = viewController.map
if map.selectedMarker != selectedMarker {
map.selectedMarker = selectedMarker
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
map.animate(toZoom: kGMSMinZoomLevel)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
map.animate(with: GMSCameraUpdate.setTarget(selectedMarker.position))
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
map.animate(toZoom: 12)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
// Invoke onAnimationEnded() once the animation sequence completes
onAnimationEnded()
})
})
}
}
}
}
}
onAnimationEnded
inMapViewControllerBridge
implementieren
Implementiere die onAnimationEnded
-Sperrung, bei der MapViewControllerBridge
innerhalb von ContentView
instanziiert wird. Kopiere den folgenden Code und füge ihn ein. Dabei wird ein neuer Status namens zoomInCenter
hinzugefügt. Außerdem wird die Ansicht mithilfe von clipShape
geändert. Der Durchmesser der abgeschnittenen Form hängt vom Wert von zoomInCenter
ab.
Contentansicht
struct ContentView: View {
@State var zoomInCenter: Bool = false
// ...
var body: some View {
// ...
GeometryReader { geometry in
ZStack(alignment: .top) {
// Map
let diameter = zoomInCenter ? geometry.size.width : (geometry.size.height * 2)
MapViewControllerBridge(markers: $markers, selectedMarker: $selectedMarker, onAnimationEnded: {
self.zoomInCenter = true
})
.clipShape(
Circle()
.size(
width: diameter,
height: diameter
)
.offset(
CGPoint(
x: (geometry.size.width - diameter) / 2,
y: (geometry.size.height - diameter) / 2
)
)
)
.animation(.easeIn)
.background(Color(red: 254.0/255.0, green: 1, blue: 220.0/255.0))
}
}
}
}
- Starten Sie die App und sehen Sie sich die Animationen an!
9. Ereignis an SwiftUI senden
In diesem Schritt werden die von GMSMapView
ausgegebenen Ereignisse überwacht und an SwiftUI gesendet. Insbesondere legen Sie einen Bevollmächtigten für die Kartenansicht fest und erfassen Kamera-Ereignisbewegungen, sodass, wenn eine Stadt fokussiert und die Kamera von einer Geste entfernt wird, die Kartenansicht von der Karte entfernt wird, sodass Sie einen größeren Teil der Karte sehen können.
Verwendung von SwiftUI-Koordinatoren
GMSMapView
löst Ereignisse aus, z. B. wenn sich die Kameraposition ändert oder wenn auf eine Markierung getippt wird. Der Mechanismus zur Überwachung dieser Ereignisse erfolgt über das GMSMapViewDelegate-Protokoll. Mit SwiftUI wird das Konzept eines Koordinators vorgestellt, das speziell als Bevollmächtigter für UIKit-Ansicht-Controller verwendet wird. Im SwiftUI-Bereich sollte ein Koordinator also für die Einhaltung des GMSMapViewDelegate
-Protokolls verantwortlich sein. Dazu müssen Sie die folgenden Schritte ausführen:
- Erstellen Sie einen Koordinator namens
MapViewCoordinator
inMapViewControllerBridge
Erstelle eine verschachtelte Klasse innerhalb der Klasse MapViewControllerBridge
und rufe sie MapViewCoordinator
auf. Diese Klasse sollte GMSMapViewDelegate
entsprechen und MapViewControllerBridge
als Eigenschaft deklarieren.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
// ...
final class MapViewCoordinator: NSObject, GMSMapViewDelegate {
var mapViewControllerBridge: MapViewControllerBridge
init(_ mapViewControllerBridge: MapViewControllerBridge) {
self.mapViewControllerBridge = mapViewControllerBridge
}
}
}
makeCoordinator()
inMapViewControllerBridge
implementieren
Implementiere als Nächstes die Methode makeCoordinator()
in MapViewControllerBridge
und gib eine Instanz von MapViewCoodinator
zurück, die du im vorherigen Schritt erstellt hast.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
// ...
func makeCoordinator() -> MapViewCoordinator {
return MapViewCoordinator(self)
}
}
MapViewCoordinator
als Bevollmächtigten für die Kartenansicht festlegen
Im nächsten Schritt wird der benutzerdefinierte Koordinator als Bevollmächtigter für die Kartenansicht des Ansichts-Controllers festgelegt. Aktualisieren Sie dazu die Initialisierung des Ansichts-Controllers in makeUIViewController(context)
. Der erstellte Koordinator des vorherigen Schritts ist über das Kontextobjekt zugänglich.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
// ...
func makeUIViewController(context: Context) -> MapViewController {
let uiViewController = MapViewController()
uiViewController.map.delegate = context.coordinator
return uiViewController
}
- Du kannst
MapViewControllerBridge
einen Ausschluss hinzufügen, damit das Ereignis zum Bewegen der Kamera übertragen werden kann
Da die Ansicht mit den Kamerabewegungen aktualisiert werden soll, muss eine neue Schließen-Eigenschaft deklariert werden, die einen booleschen Wert innerhalb von MapViewControllerBridge
mit dem Namen mapViewWillMove
akzeptiert und diese Öffnung in der delegierten Methode mapView(_, willMove)
in MapViewCoordinator
aufruft. Übergeben Sie den Wert von gesture
an die Öffnung, damit die SwiftUI-Ansicht nur auf bewegungsbezogene Kamera-Bewegungsereignisse reagieren kann.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
var mapViewWillMove: (Bool) -> ()
//...
final class MapViewCoordinator: NSObject, GMSMapViewDelegate {
// ...
func mapView(_ mapView: GMSMapView, willMove gesture: Bool) {
self.mapViewControllerBridge.mapViewWillMove(gesture)
}
}
}
- Aktualisieren Sie ContentView, um einen Wert für
mapWillMove
zu übergeben
Wenn die neue Sperrung am MapViewControllerBridge
deklariert ist, aktualisieren Sie ContentView
, damit ein Wert für diese neue Schließung übergeben wird. Ändere in diesem Fall den Status zoomInCenter
in false
, wenn sich das Ereignis „Verschieben“ auf eine Geste bezieht. So wird die Karte wieder vollständig angezeigt, wenn die Karte durch eine Geste verschoben wird.
Contentansicht
struct ContentView: View {
@State var zoomInCenter: Bool = false
// ...
var body: some View {
// ...
GeometryReader { geometry in
ZStack(alignment: .top) {
// Map
let diameter = zoomInCenter ? geometry.size.width : (geometry.size.height * 2)
MapViewControllerBridge(markers: $markers, selectedMarker: $selectedMarker, onAnimationEnded: {
self.zoomInCenter = true
}, mapViewWillMove: { (isGesture) in
guard isGesture else { return }
self.zoomInCenter = false
})
// ...
}
}
}
}
- Führe die App aus, um die neuen Änderungen zu sehen.
10. Glückwunsch
Glückwunsch! Sie haben viel gelernt und hoffentlich können Sie mit den gewonnenen Erkenntnissen jetzt Ihre eigene SwiftUI-App mit dem Maps SDK for iOS erstellen.
Das haben Sie gelernt
- Die Unterschiede zwischen SwiftUI und UIKit
- Die Überbrückung von SwiftUI und UIKit mit UIViewControllerRepresentable
- Mit der Funktion State und mit der Bindung Änderungen an der Kartenansicht vornehmen
- Ereignis über einen Koordinator aus der Kartenansicht an SwiftUI senden
Nächste Schritte
- Maps SDK for iOS – offizielle Dokumentation zum Maps SDK for iOS
- Places SDK for iOS: Unternehmen und Sehenswürdigkeiten in der Nähe finden
- maps-sdk-for-ios-samples – Beispielcode auf GitHub, in dem alle Funktionen im Maps SDK for iOS demonstriert werden.
- SwiftUI – offizielle Dokumentation zu SwiftUI von Apple
- Hilf uns, die Inhalte zu erstellen, die für dich am nützlichsten wären. Beantworten Sie dazu die folgende Frage:
Welche weiteren Codelabs möchten Sie sehen?
Ist das Codelab, das oben nicht aufgeführt werden soll? Hier können Sie ein neues Problem beantragen.