1. Sebelum Memulai
Codelab ini mengajarkan Anda cara menggunakan Maps SDK for iOS dengan SwiftUI.
Prasyarat
- Pengetahuan dasar Swift
- Pemahaman dasar tentang SwiftUI
Yang akan Anda lakukan
- Mengaktifkan dan menggunakan Maps SDK for iOS untuk menambahkan Google Maps ke aplikasi iOS menggunakan SwiftUI.
- Menambahkan penanda ke peta.
- Meneruskan status dari tampilan SwiftUI ke objek
GMSMapView
dan sebaliknya.
Yang akan Anda perlukan
- Xcode 11.0 atau versi yang lebih baru
- Akun Google dengan penagihan diaktifkan
- Maps SDK for iOS
- Carthage
2. Memulai persiapan
Untuk langkah pengaktifan berikut, aktifkan Maps SDK for iOS.
Menyiapkan Google Maps Platform
Jika Anda belum memiliki akun Google Cloud Platform dan project dengan penagihan diaktifkan, lihat panduan Memulai Google Maps Platform untuk membuat akun penagihan dan project.
- Di Cloud Console, klik menu drop-down project lalu pilih project yang ingin Anda gunakan untuk codelab ini.
- Aktifkan API dan SDK Google Maps Platform yang diperlukan untuk codelab ini di Google Cloud Marketplace. Untuk melakukannya, ikuti langkah-langkah dalam video ini atau dokumentasi ini.
- Buat kunci API di halaman Kredensial di Cloud Console. Anda dapat mengikuti langkah-langkah dalam video ini atau dokumentasi ini. Semua permintaan ke Google Maps Platform memerlukan kunci API.
3. Mendownload kode awal
Untuk membantu Anda memulai secepatnya, berikut beberapa kode awal untuk membantu Anda mengikuti codelab ini. Anda dapat langsung ke bagian solusi, namun jika Anda ingin mengikuti semua langkah untuk membuatnya sendiri, baca semuanya.
- Lakukan clone repositori jika sudah menginstal
git
.
git clone https://github.com/googlecodelabs/maps-ios-swiftui.git
Atau, Anda dapat mengklik tombol berikut untuk mendownload kode sumber.
- Setelah mendapatkan kode, di terminal
cd
pilih direktoristarter/GoogleMapsSwiftUI
. - Jalankan
carthage update --platform iOS
untuk mendownload Maps SDK for iOS - Terakhir, buka file
GoogleMapsSwiftUI.xcodeproj
di Xcode
4. Ringkasan Kode
Dalam project permulaan yang Anda download, class berikut telah disediakan dan diterapkan untuk Anda:
AppDelegate
-UIApplicationDelegate
aplikasi. Di sini tempat Maps SDK for iOS akan diinisialisasi.City
- struct yang mewakili kota (berisi nama dan koordinat kota).MapViewController
-UIViewController
UIKit sederhana yang berisi Google Maps (GMSMapView)SceneDelegate
-UIWindowSceneDelegate
aplikasi tempat instanceContentView
dibuat.
Selain itu, class berikut memiliki penerapan parsial dan akan Anda selesaikan pada akhir Codelab ini:
ContentView
- tampilan SwiftUI tingkat teratas yang berisi aplikasi Anda.MapViewControllerBridge
- class yang menjembatani tampilan UIKit ke tampilan SwiftUI. Secara khusus, ini adalah class yang akan membuatMapViewController
dapat diakses di SwiftUI.
5. Menggunakan SwiftUI vs. UIKit
SwiftUI diperkenalkan di iOS 13 sebagai framework UI alternatif pengganti UIKit untuk mengembangkan aplikasi iOS. Dibandingkan dengan UIKit pendahulunya, SwiftUI menawarkan sejumlah keuntungan. Di antaranya:
- Tampilan diperbarui secara otomatis saat status berubah. Menggunakan objek yang disebut Status, setiap perubahan pada nilai dasar di dalamnya akan menyebabkan UI diperbarui secara otomatis.
- Pratinjau langsung memungkinkan pengembangan yang lebih cepat. Pratinjau langsung meminimalkan kebutuhan untuk mem-build dan men-deploy kode ke emulator untuk melihat perubahan visual karena pratinjau tampilan SwiftUI dapat langsung dilihat di Xcode.
- Sumber tepercaya ada di Swift. Semua tampilan di SwiftUI dideklarasikan di Swift, sehingga penggunaan Interface Builder tidak lagi diperlukan.
- Interoperabilitas dengan UIKit. Interoperabilitas dengan UIKit memastikan aplikasi yang ada dapat menggunakan SwiftUI secara bertahap bersama dengan tampilan yang ada. Selain itu, library yang belum mendukung SwiftUI, seperti Maps SDK for iOS, masih dapat digunakan di SwiftUI.
Tetapi ada juga beberapa kekurangan:
- SwiftUI hanya tersedia di iOS 13 atau versi yang lebih baru.
- Hierarki tampilan tidak dapat diperiksa dalam pratinjau Xcode.
Status dan aliran data SwiftUI
SwiftUI menawarkan cara baru untuk membuat UI menggunakan pendekatan deklaratif—Anda memberi tahu SwiftUI bagaimana Anda ingin tampilan diperlihatkan bersama dengan semua statusnya yang berbeda, dan sistem akan melakukan sisanya. SwiftUI menangani pembaruan tampilan setiap kali status yang mendasari berubah karena adanya peristiwa atau tindakan pengguna. Desain ini biasanya disebut aliran data searah. Meskipun spesifikasi desain ini berada di luar cakupan dalam codelab ini, sebaiknya Anda membaca cara kerjanya dalam dokumentasi Status dan Aliran Data Apple.
Menjembatani UIKit dan SwiftUI menggunakan UIViewRepresentable atau UIViewControllerRepresentable
Karena Maps SDK for iOS dibuat atas dasar UIKit dan belum menyediakan tampilan yang kompatibel dengan SwiftUI, penggunaannya di SwiftUI harus sesuai dengan UIViewRepresentable
atau UIViewControllerRepresentable
. Protokol ini memungkinkan SwiftUI menyertakan UIView
dan UIViewController
yang dibuat UIKit. Meskipun Anda dapat menggunakan salah satu protokol untuk menambahkan Google Maps ke tampilan SwiftUI, pada langkah berikutnya, kita akan melihat penggunaan UIViewControllerRepresentable
untuk menyertakan UIViewController
yang berisi peta.
6. Menambahkan peta
Di bagian ini, Anda akan menambahkan Google Maps ke tampilan SwiftUI.
Menambahkan kunci API
Kunci API yang Anda buat di langkah sebelumnya harus diberikan ke Maps SDK for iOS untuk mengaitkan akun Anda dengan peta yang akan ditampilkan di aplikasi.
Untuk memberikan kunci API Anda, buka file AppDelegate.swift
lalu buka metode application(_, didFinishLaunchingWithOptions)
. Saat ini, SDK diinisialisasi melalui GMSServices.provideAPIKey()
dengan string "YOUR_API_KEY". Ganti string tersebut dengan kunci API Anda. Dengan menyelesaikan langkah ini, Maps SDK for iOS akan diinisialisasi saat aplikasi diluncurkan.
Menambahkan Google Maps menggunakan MapViewControllerBridge
Setelah kunci API Anda diberikan ke SDK, langkah berikutnya adalah menampilkan peta di aplikasi.
Pengontrol tampilan yang disediakan dalam kode awal, MapViewController
, saat ini berisi GMSMapView
dalam tampilannya. Namun, karena pengontrol tampilan ini dibuat di UIKit, Anda harus menjembatani class ini ke SwiftUI sehingga dapat digunakan di dalam ContentView
. Untuk melakukannya:
- Buka file
MapViewControllerBridge
di Xcode.
Class ini sesuai dengan UIViewControllerRepresentable yang merupakan protokol yang diperlukan untuk menggabungkan UIViewController
UIKit, sehingga dapat digunakan sebagai tampilan SwiftUI. Dengan kata lain, mematuhi protokol ini memungkinkan Anda menjembatani tampilan UIKit ke tampilan SwiftUI. Untuk mematuhi protokol ini, diperlukan penerapan dua metode:
makeUIViewController(context)
- metode ini dipanggil oleh SwiftUI untuk membuatUIViewController
yang mendasari. Di sini Anda akan membuat instanceUIViewController
dan meneruskan status awalnya.updateUIViewController(_, context)
- metode ini dipanggil oleh SwiftUI setiap kali status berubah. Di sini Anda akan melakukan modifikasi padaUIViewController
yang mendasari untuk bereaksi sebagai respons terhadap perubahan status.
- Buat
MapViewController
Di dalam fungsi makeUIViewController(context)
, buat instance MapViewController
baru dan tampilkan sebagai hasilnya. Setelah melakukannya, MapViewControllerBridge
Anda sekarang akan terlihat seperti ini:
MapViewControllerBridge
import GoogleMaps
import SwiftUI
struct MapViewControllerBridge: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> MapViewController {
return MapViewController()
}
func updateUIViewController(_ uiViewController: MapViewController, context: Context) {
}
}
Menggunakan MapViewControllerBridge di ContentView
Setelah MapViewControllerBridge
membuat instance MapViewController
, langkah berikutnya adalah menggunakan struct ini dalam ContentView
untuk menampilkan peta.
- Buka file
ContentView
di Xcode.
ContentView
dibuat instance-nya di SceneDelegate
dan berisi tampilan aplikasi tingkat atas. Peta akan ditambahkan dari dalam file ini.
- Buat
MapViewControllerBridge
dalam propertibody
.
Dalam properti body
file ini, ZStack
telah disediakan dan diterapkan untuk Anda. ZStack
saat ini berisi daftar kota yang dapat berinteraksi dan dapat ditarik yang akan Anda gunakan di langkah berikutnya. Untuk saat ini, dalam ZStack
, buat MapViewControllerBridge
sebagai tampilan turunan pertama ZStack
, sehingga peta akan ditampilkan di aplikasi di belakang tampilan daftar kota. Setelah melakukannya, konten properti body
dalam ContentView
akan terlihat seperti ini:
ContentView
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()
} // ...
}
}
}
- Sekarang lanjutkan dan jalankan aplikasi. Anda akan melihat peta dimuat di layar perangkat beserta daftar kota yang dapat ditarik ke bagian bawah layar.
7. Menambahkan penanda ke peta
Pada langkah sebelumnya, Anda menambahkan peta bersama daftar yang dapat berinteraksi yang menampilkan daftar kota. Di bagian ini, Anda akan menambahkan penanda untuk setiap kota dalam daftar tersebut.
Penanda sebagai Status
ContentView
saat ini mendeklarasikan properti bernama markers
yang merupakan daftar GMSMarker
. Kode ini mewakili setiap kota yang dideklarasikan di properti statis cities
. Perhatikan bahwa properti ini dianotasi dengan Status wrapper properti SwiftUI untuk menunjukkan bahwa properti ini akan dikelola oleh SwiftUI. Jadi, jika ada perubahan yang terdeteksi dengan properti ini, seperti menambahkan atau menghapus penanda, tampilan yang menggunakan status ini akan diperbarui.
ContentView
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
}
Perhatikan bahwa ContentView
menggunakan properti markers
untuk merender daftar kota dengan meneruskannya ke class CitiesList
.
CitiesList
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)
}
}
}
}
Meneruskan Status ke MapViewControllerBridge melalui Binding
Selain daftar kota yang menampilkan data dari properti markers
, teruskan properti ini ke struct MapViewControllerBridge
agar dapat digunakan untuk menampilkan penanda tersebut pada peta. Untuk melakukannya:
- Deklarasikan properti
markers
baru dalamMapViewControllerBridge
yang dianotasi dengan@Binding
MapViewControllerBridge
struct MapViewControllerBridge: : UIViewControllerRepresentable {
@Binding var markers: [GMSMarker]
// ...
}
- Di
MapViewControllerBridge
, perbarui metodeupdateUIViewController(_, context)
untuk memanfaatkan propertimarkers
Seperti yang disebutkan di langkah sebelumnya, updateUIViewController(_, context)
akan dipanggil oleh SwiftUI setiap kali status berubah. Dalam metode inilah kita ingin memperbarui peta sehingga menampilkan penanda di markers
. Untuk melakukannya, Anda harus memperbarui properti map
setiap penanda. Setelah menyelesaikan langkah ini, MapViewControllerBridge
Anda akan terlihat seperti ini:
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 }
}
}
- Teruskan properti
markers
dariContentView
keMapViewControllerBridge
Karena Anda menambahkan properti baru di MapViewControllerBridge
, maka nilai untuk properti ini harus diteruskan ke penginisialisasi untuk MapViewControllerBridge
. Jadi, jika Anda mencoba mem-build aplikasi, Anda akan melihat bahwa aplikasi tidak akan dikompilasi. Untuk memperbaikinya, lakukan pembaruan pada ContentView
tempat MapViewControllerBridge
dibuat dan teruskan properti markers
seperti berikut:
struct ContentView: View {
// ...
var body: some View {
// ...
GeometryReader { geometry in
ZStack(alignment: .top) {
// Map
MapViewControllerBridge(markers: $markers)
// ...
}
}
}
}
Perhatikan bahwa awalan $
digunakan untuk meneruskan markers
ke MapViewControllerBridge
karena mengharapkan properti terikat. $
adalah awalan yang dicadangkan untuk digunakan dengan wrapper properti Swift. Jika diterapkan ke Status, tindakan ini akan menampilkan Binding.
- Lanjutkan dan jalankan aplikasi untuk melihat penanda yang ditampilkan di peta.
8. Menganimasikan ke kota yang dipilih
Pada langkah sebelumnya, Anda menambahkan penanda ke peta dengan meneruskan Status dari satu tampilan SwiftUI ke tampilan lainnya. Pada langkah ini, Anda akan menganimasikan peta ke kota/penanda setelah diketuk di daftar yang dapat berinteraksi. Untuk menjalankan animasi, Anda akan bereaksi terhadap perubahan pada Status dengan memodifikasi posisi kamera peta saat perubahan tersebut terjadi. Untuk mempelajari lebih lanjut konsep kamera peta, lihat Kamera dan Tampilan.
Menganimasikan peta ke kota yang dipilih
Untuk menganimasikan peta ke kota yang dipilih:
- Tentukan Binding baru di
MapViewControllerBridge
ContentView
memiliki properti Status yang disebut selectedMarker
yang diinisialisasi ke nilai nol dan mendapatkan pembaruan setiap kali kota dipilih dalam daftar. Proses ini ditangani oleh tampilan CitiesList
buttonAction
dalam ContentView
.
ContentView
CitiesList(markers: $markers) { (marker) in
guard self.selectedMarker != marker else { return }
self.selectedMarker = marker
// ...
}
Setiap kali selectedMarker
berubah, MapViewControllerBridge
harus mengetahui perubahan status ini agar dapat menganimasikan peta ke penanda yang dipilih. Jadi, tentukan Binding baru dalam MapViewControllerBridge
dari jenis GMSMarker
lalu beri nama properti selectedMarker
.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
@Binding var selectedMarker: GMSMarker?
}
- Perbarui
MapViewControllerBridge
untuk menganimasikan peta setiap kaliselectedMarker
berubah
Setelah Binding baru dideklarasikan, Anda perlu memperbarui fungsi updateUIViewController_, context)
MapViewControllerBridge
agar peta dianimasikan ke penanda yang dipilih. Lanjutkan dengan menyalin kode di bawah ini:
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)
})
}
}
}
}
}
Fungsi animateToSelectedMarker(viewController)
akan menjalankan urutan animasi peta menggunakan fungsi animate(with)
GMSMapView
.
- Teruskan
selectedMarker
ContentView
keMapViewControllerBridge
Setelah Binding baru MapViewControllerBridge
dideklarasikan, lanjutkan dan perbarui ContentView
untuk diteruskan ke selectedMarker
tempat MapViewControllerBridge
dibuat instance-nya.
ContentView
struct ContentView: View {
// ...
var body: some View {
// ...
GeometryReader { geometry in
ZStack(alignment: .top) {
// Map
MapViewControllerBridge(markers: $markers, selectedMarker: $selectedMarker)
// ...
}
}
}
}
Menyelesaikan langkah ini sekarang akan menganimasikan peta setiap kali kota baru dipilih dalam daftar.
Menganimasikan tampilan SwiftUI untuk menekankan kota
SwiftUI membuat animasi tampilan menjadi sangat mudah karena SwiftUI akan menangani performa animasi untuk transisi Status. Untuk mendemonstrasikan ini, Anda akan menambahkan lebih banyak animasi dengan memfokuskan tampilan ke kota yang dipilih setelah animasi peta selesai. Untuk melakukannya, selesaikan langkah-langkah berikut:
- Tambahkan penutupan
onAnimationEnded
keMapViewControllerBridge
Karena animasi SwiftUI akan dijalankan setelah urutan animasi peta yang Anda tambahkan sebelumnya, deklarasikan penutupan baru bernama onAnimationEnded
dalam MapViewControllerBridge
, lalu panggil penutupan ini setelah penundaan 0,5 detik setelah animasi peta terakhir dalam metode animateToSelectedMarker(viewController)
.
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()
})
})
}
}
}
}
}
- Terapkan
onAnimationEnded
diMapViewControllerBridge
Terapkan penutupan onAnimationEnded
tempat MapViewControllerBridge
dibuat instance-nya dalam ContentView
. Salin dan tempelkan kode berikut yang menambahkan Status baru bernama zoomInCenter
sekaligus mengubah tampilan menggunakan clipShape
dan memvariasikan diameter bentuk yang terpotong bergantung pada nilai zoomInCenter
ContentView
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))
}
}
}
}
- Lanjutkan dan jalankan aplikasi untuk melihat animasi.
9. Mengirim peristiwa ke SwiftUI
Pada langkah ini, Anda akan memproses peristiwa yang dikeluarkan dari GMSMapView
, dan mengirimkan peristiwa tersebut ke SwiftUI. Secara khusus, Anda akan menetapkan delegasi ke tampilan peta dan memproses peristiwa gerakan kamera, sehingga saat kota difokuskan dan kamera peta bergerak dari gestur, tampilan peta tidak akan fokus agar Anda bisa melihat semakin banyak peta.
Menggunakan Koordinator SwiftUI
GMSMapView
memunculkan peristiwa seperti perubahan posisi kamera atau saat penanda diketuk. Mekanisme untuk memproses peristiwa ini adalah melalui protokol GMSMapViewDelegate. SwiftUI memperkenalkan konsep Koordinator yang digunakan secara khusus untuk bertindak sebagai delegasi untuk pengontrol tampilan UIKit. Jadi, dalam dunia SwiftUI, Koordinator harus bertanggung jawab untuk mematuhi protokol GMSMapViewDelegate
. Untuk melakukannya, selesaikan langkah-langkah berikut:
- Buat Koordinator yang disebut
MapViewCoordinator
dalamMapViewControllerBridge
Buat class bersarang di dalam class MapViewControllerBridge
dan beri nama MapViewCoordinator
. Class ini harus sesuai dengan GMSMapViewDelegate
dan harus mendeklarasikan MapViewControllerBridge
sebagai properti.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
// ...
final class MapViewCoordinator: NSObject, GMSMapViewDelegate {
var mapViewControllerBridge: MapViewControllerBridge
init(_ mapViewControllerBridge: MapViewControllerBridge) {
self.mapViewControllerBridge = mapViewControllerBridge
}
}
}
- Terapkan
makeCoordinator()
diMapViewControllerBridge
Selanjutnya, terapkan metode makeCoordinator()
dalam MapViewControllerBridge
dan tampilkan instance MapViewCoodinator
yang Anda buat di langkah sebelumnya.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
// ...
func makeCoordinator() -> MapViewCoordinator {
return MapViewCoordinator(self)
}
}
- Tetapkan
MapViewCoordinator
sebagai delegasi tampilan peta
Setelah koordinator kustom dibuat, langkah berikutnya adalah menetapkan koordinator sebagai delegasi untuk tampilan peta pengontrol tampilan. Untuk melakukannya, perbarui inisialisasi pengontrol tampilan di makeUIViewController(context)
. Koordinator yang dibuat dari langkah sebelumnya akan dapat diakses dari objek Context.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
// ...
func makeUIViewController(context: Context) -> MapViewController {
let uiViewController = MapViewController()
uiViewController.map.delegate = context.coordinator
return uiViewController
}
- Tambahkan penutupan ke
MapViewControllerBridge
sehingga kamera yang akan memindahkan peristiwa dapat diterapkan
Karena tujuannya adalah memperbarui tampilan dengan gerakan kamera, deklarasikan properti penutupan baru yang menerima boolean dalam MapViewControllerBridge
yang disebut mapViewWillMove
, lalu panggil penutupan ini di metode delegasi mapView(_, willMove)
dalam MapViewCoordinator
. Teruskan nilai gesture
ke penutupan, sehingga tampilan SwiftUI hanya dapat bereaksi terhadap peristiwa gerakan kamera terkait gestur.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
var mapViewWillMove: (Bool) -> ()
//...
final class MapViewCoordinator: NSObject, GMSMapViewDelegate {
// ...
func mapView(_ mapView: GMSMapView, willMove gesture: Bool) {
self.mapViewControllerBridge.mapViewWillMove(gesture)
}
}
}
- Perbarui ContentView agar meneruskan nilai untuk
mapWillMove
Dengan penutupan baru yang dideklarasikan di MapViewControllerBridge
, perbarui ContentView
agar dapat meneruskan nilai untuk penutupan baru ini. Dalam penutupan tersebut, alihkan Status zoomInCenter
ke false
jika peristiwa pergerakan terkait dengan gestur. Ini akan secara efektif menampilkan peta dalam tampilan lengkap lagi saat peta digerakkan oleh gestur.
ContentView
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
})
// ...
}
}
}
}
- Lanjutkan dan jalankan aplikasi untuk melihat perubahan baru.
10. Selamat
Selamat karena telah membaca sampai sini. Anda telah mempelajari banyak hal, dan semoga pelajaran yang telah didapatkan tersebut membuat Anda kini bisa membuat sendiri aplikasi SwiftUI menggunakan Maps SDK for iOS.
Yang telah Anda pelajari
- Perbedaan antara SwiftUI dan UIKit
- Cara menjembatani SwiftUI dan UIKit menggunakan UIViewControllerRepresentable
- Cara membuat perubahan pada tampilan peta dengan Status dan Binding
- Cara mengirim peristiwa dari tampilan peta ke SwiftUI menggunakan Koordinator
Apa selanjutnya?
- Maps SDK for iOS - dokumentasi resmi untuk Maps SDK for iOS
- Places SDK for iOS - menemukan bisnis lokal dan lokasi menarik di sekitar Anda
- maps-sdk-for-ios-samples - kode contoh di GitHub yang menunjukkan semua fitur dalam Maps SDK for iOS.
- SwiftUI - Dokumentasi resmi Apple tentang SwiftUI
- Bantu kami membuat konten yang menurut Anda paling berguna dengan menjawab pertanyaan di bawah:
Apa saja codelab lain yang ingin Anda lihat?
Apakah codelab yang Anda inginkan tidak tercantum di atas? Ajukan permintaan bersama masalah baru di sini.