1. शुरू करने से पहले
इस कोडलैब में, SwiftUI के साथ iOS के लिए Maps SDK का इस्तेमाल करने का तरीका बताया गया है.
ज़रूरी शर्तें
- Swift की बुनियादी जानकारी
- SwiftUI के बारे में बुनियादी जानकारी
आपको क्या करना होगा
- SwiftUI का इस्तेमाल करके, iOS ऐप्लिकेशन में Google Maps जोड़ने के लिए, iOS के लिए Maps SDK को चालू करें और उसका इस्तेमाल करें.
- मैप में मार्कर जोड़ें.
- SwiftUI और
GMSMapView
ऑब्जेक्ट के बीच स्थिति को पास करें.
आपको किन चीज़ों की ज़रूरत होगी
- Xcode 11.0 या इसके बाद का वर्शन
- बिलिंग की सुविधा वाला Google खाता
- iOS के लिए Maps SDK
- कार्थेज
2. सेट अप करें
इसके बाद, iOS के लिए Maps SDK चालू करें.
Google Maps Platform सेट अप करना
अगर आपके पास Google Cloud Platform खाता और बिलिंग की सुविधा वाला प्रोजेक्ट नहीं है, तो बिलिंग की सुविधा वाला खाता और प्रोजेक्ट बनाएं. ऐसा करने का तरीका जानने के लिए, कृपया Google Maps Platform का इस्तेमाल शुरू करना देखें.
- Cloud Console में, प्रोजेक्ट वाले ड्रॉप-डाउन मेन्यू पर क्लिक करें. इसके बाद, उस प्रोजेक्ट को चुनें जिसे इस कोडलैब के लिए इस्तेमाल करना है.
- इस कोडलैब के लिए ज़रूरी Google Maps Platform API और एसडीके को Google Cloud Marketplace में जाकर चालू करें. ऐसा करने के लिए, इस वीडियो या दस्तावेज़ में बताया गया तरीका अपनाएं.
- Cloud Console के क्रेडेंशियल पेज पर जाकर, एक एपीआई पासकोड जनरेट करें. ऐसा करने के लिए, इस वीडियो या दस्तावेज़ में बताया गया तरीका अपनाएं. Google Maps Platform का इस्तेमाल करने के लिए, एपीआई पासकोड ज़रूरी है.
3. स्टार्टर कोड डाउनलोड करना
इस कोडलैब को जल्द से जल्द शुरू करने के लिए, यहां कुछ शुरुआती कोड दिए गए हैं. आपके पास सीधे समाधान पर जाने का विकल्प है. हालांकि, अगर आपको इसे खुद बनाने के लिए सभी चरणों का पालन करना है, तो पढ़ना जारी रखें.
- अगर आपने
git
इंस्टॉल किया है, तो रिपॉज़िटरी को क्लोन करें.
git clone https://github.com/googlecodelabs/maps-ios-swiftui.git
इसके अलावा, सोर्स कोड को डाउनलोड करने के लिए, इस बटन पर क्लिक करें.
- कोड मिलने के बाद, टर्मिनल में
cd
डायरेक्ट्री मेंstarter/GoogleMapsSwiftUI
डालें. - iOS के लिए Maps SDK टूल डाउनलोड करने के लिए,
carthage update --platform iOS
चलाएं - आखिर में,
GoogleMapsSwiftUI.xcodeproj
फ़ाइल को Xcode में खोलें
4. कोड के बारे में खास जानकारी
आपने जो स्टार्टर प्रोजेक्ट डाउनलोड किया है उसमें ये क्लास पहले से मौजूद हैं और इन्हें लागू किया गया है:
AppDelegate
- ऐप्लिकेशन काUIApplicationDelegate
. Maps SDK for iOS को यहां शुरू किया जाएगा.City
- यह एक स्ट्रक्चर है, जो किसी शहर को दिखाता है. इसमें शहर का नाम और उसके निर्देशांक शामिल होते हैं.MapViewController
- यह एक स्कोप-डाउन UIKitUIViewController
है, जिसमें Google Map (GMSMapView)- शामिल है
SceneDelegate
- ऐप्लिकेशन काUIWindowSceneDelegate
, जिससेContentView
इंस्टैंटिएट किया जाता है.
इसके अलावा, यहां दी गई क्लास में कुछ फ़ंक्शन पहले से लागू हैं. आपको इस कोडलैब के आखिर तक, इन क्लास में बाकी फ़ंक्शन लागू करने होंगे:
ContentView
- यह आपके ऐप्लिकेशन को शामिल करने वाला टॉप-लेवल का SwiftUI व्यू है.MapViewControllerBridge
- यह एक ऐसी क्लास है जो UIKit व्यू को SwiftUI व्यू से जोड़ती है. खास तौर पर, यह ऐसी क्लास है जो SwiftUI मेंMapViewController
को ऐक्सेस करने की सुविधा देगी.
5. SwiftUI बनाम UIKit
SwiftUI को iOS 13 में, iOS ऐप्लिकेशन डेवलप करने के लिए UIKit के विकल्प के तौर पर पेश किया गया था. SwiftUI, अपने पुराने वर्शन UIKit की तुलना में कई फ़ायदे देता है. इनमें से कुछ के नाम यहां दिए गए हैं:
- स्थिति बदलने पर, व्यू अपने-आप अपडेट हो जाते हैं. State नाम के ऑब्जेक्ट का इस्तेमाल करके, इसमें मौजूद वैल्यू में कोई भी बदलाव करने पर यूज़र इंटरफ़ेस (यूआई) अपने-आप अपडेट हो जाएगा.
- लाइव प्रीव्यू की मदद से, तेज़ी से डेवलपमेंट किया जा सकता है. लाइव झलक की सुविधा से, कोड को बनाने और उसे एम्युलेटर पर डिप्लॉय करने की ज़रूरत कम हो जाती है. ऐसा इसलिए, क्योंकि SwiftUI व्यू की झलक को Xcode पर आसानी से देखा जा सकता है.
- सोर्स-ऑफ़-ट्रुथ, Swift में है. SwiftUI में सभी व्यू, Swift में डिक्लेयर किए जाते हैं. इसलिए, अब Interface Builder का इस्तेमाल करना ज़रूरी नहीं है.
- यह UIKit के साथ काम करता है. UIKit के साथ इंटरऑपरेबिलिटी की सुविधा होने से, मौजूदा ऐप्लिकेशन अपने मौजूदा व्यू के साथ-साथ, SwiftUI का इस्तेमाल कर सकते हैं. इसके अलावा, जिन लाइब्रेरी में अब तक SwiftUI का इस्तेमाल नहीं किया जा सकता, जैसे कि Maps SDK for iOS, उन्हें अब भी SwiftUI में इस्तेमाल किया जा सकता है.
इसके कुछ नुकसान भी हैं:
- SwiftUI सिर्फ़ iOS 13 या उसके बाद के वर्शन पर उपलब्ध है.
- Xcode की झलक में व्यू हैरारकी की जांच नहीं की जा सकती.
SwiftUI स्टेट और डेटा फ़्लो
SwiftUI, यूज़र इंटरफ़ेस (यूआई) बनाने का एक नया तरीका है. इसमें डिक्लेरेटिव अप्रोच का इस्तेमाल किया जाता है. इसमें आपको SwiftUI को यह बताना होता है कि आपको अपना व्यू कैसा दिखाना है. साथ ही, इसके लिए अलग-अलग स्थितियां भी बतानी होती हैं. इसके बाद, सिस्टम बाकी काम अपने-आप कर देता है. SwiftUI, इवेंट या उपयोगकर्ता की कार्रवाई की वजह से, व्यू में होने वाले बदलावों को अपने-आप अपडेट करता है. इस डिज़ाइन को आम तौर पर एकतरफ़ा डेटा फ़्लो कहा जाता है. इस कोडलैब में, इस डिज़ाइन के बारे में ज़्यादा जानकारी नहीं दी गई है. हालांकि, हमारा सुझाव है कि आप Apple के स्टेट और डेटा फ़्लो के दस्तावेज़ में, इसके काम करने के तरीके के बारे में पढ़ें.
UIViewRepresentable या UIViewControllerRepresentable का इस्तेमाल करके, UIKit और SwiftUI को ब्रिज करना
iOS के लिए Maps SDK को UIKit के आधार पर बनाया गया है. साथ ही, यह SwiftUI के साथ काम करने वाला व्यू नहीं देता है. इसलिए, SwiftUI में इसका इस्तेमाल करने के लिए, UIViewRepresentable
या UIViewControllerRepresentable
में से किसी एक का पालन करना ज़रूरी है. इन प्रोटोकॉल की मदद से, SwiftUI में UIKit से बनाए गए UIView
और UIViewController
शामिल किए जा सकते हैं. SwiftUI व्यू में Google Maps जोड़ने के लिए, दोनों प्रोटोकॉल का इस्तेमाल किया जा सकता है. हालांकि, अगले चरण में हम मैप वाले UIViewController
को शामिल करने के लिए, UIViewControllerRepresentable
का इस्तेमाल करने के बारे में जानेंगे.
6. मैप जोड़ना
इस सेक्शन में, Google Maps को SwiftUI व्यू में जोड़ा जाएगा.
अपनी एपीआई कुंजी जोड़ना
पिछले चरण में बनाई गई एपीआई कुंजी को Maps SDK for iOS को देना होगा, ताकि आपके खाते को उस मैप से जोड़ा जा सके जो ऐप्लिकेशन पर दिखेगा.
अपनी एपीआई कुंजी देने के लिए, AppDelegate.swift
फ़ाइल खोलें और application(_, didFinishLaunchingWithOptions)
तरीके पर जाएं. SDK टूल को GMSServices.provideAPIKey()
का इस्तेमाल करके, "YOUR_API_KEY" स्ट्रिंग के साथ शुरू किया जाता है. उस स्ट्रिंग की जगह अपना एपीआई पासकोड डालें. इस चरण को पूरा करने से, ऐप्लिकेशन लॉन्च होने पर iOS के लिए Maps SDK शुरू हो जाएगा.
MapViewControllerBridge का इस्तेमाल करके Google मैप जोड़ना
एसडीके को एपीआई पासकोड देने के बाद, अगला चरण ऐप्लिकेशन पर मैप दिखाना है.
स्टार्टर कोड में दिए गए व्यू कंट्रोलर, MapViewController
के व्यू में GMSMapView
शामिल होता है. हालांकि, इस व्यू कंट्रोलर को UIKit में बनाया गया था. इसलिए, आपको इस क्लास को SwiftUI में ब्रिज करना होगा, ताकि इसका इस्तेमाल ContentView
में किया जा सके. इसके लिए:
- Xcode में
MapViewControllerBridge
फ़ाइल खोलें.
यह क्लास, UIViewControllerRepresentable के मुताबिक है. यह एक ऐसा प्रोटोकॉल है जिसकी ज़रूरत UIKit UIViewController
को रैप करने के लिए होती है, ताकि इसे SwiftUI व्यू के तौर पर इस्तेमाल किया जा सके. दूसरे शब्दों में कहें, तो इस प्रोटोकॉल का पालन करने से, UIKit व्यू को SwiftUI व्यू से जोड़ने में आसानी होती है. इस प्रोटोकॉल का पालन करने के लिए, दो तरीकों को लागू करना ज़रूरी है:
makeUIViewController(context)
- इस तरीके को SwiftUI,UIViewController
बनाने के लिए कॉल करता है. यहां आपको अपनेUIViewController
को इंस्टैंशिएट करना होगा और उसे उसकी शुरुआती स्थिति देनी होगी.updateUIViewController(_, context)
- जब भी स्थिति बदलती है, तब SwiftUI इस तरीके को कॉल करता है. स्टेट में बदलाव होने पर,UIViewController
में कोई भी बदलाव यहां किया जा सकता है.
MapViewController
बनाएं
फ़ंक्शन makeUIViewController(context)
के अंदर, एक नया MapViewController
इंस्टैंशिएट करें और उसे नतीजे के तौर पर दिखाएं. ऐसा करने के बाद, आपका MapViewControllerBridge
अब ऐसा दिखना चाहिए:
MapViewControllerBridge
import GoogleMaps
import SwiftUI
struct MapViewControllerBridge: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> MapViewController {
return MapViewController()
}
func updateUIViewController(_ uiViewController: MapViewController, context: Context) {
}
}
ContentView में MapViewControllerBridge का इस्तेमाल करना
अब MapViewControllerBridge
, MapViewController
का इंस्टेंस बना रहा है. इसलिए, अगला चरण इस स्ट्रक्ट का इस्तेमाल ContentView
में करके, मैप दिखाना है.
- Xcode में
ContentView
फ़ाइल खोलें.
ContentView
को SceneDelegate
में इंस्टैंशिएट किया जाता है. इसमें ऐप्लिकेशन का टॉप-लेवल व्यू होता है. इस फ़ाइल से मैप जोड़ा जाएगा.
body
प्रॉपर्टी मेंMapViewControllerBridge
बनाएं.
इस फ़ाइल की body
प्रॉपर्टी में, आपके लिए ZStack
पहले से ही उपलब्ध है और इसे लागू किया जा चुका है. ZStack
में शहरों की एक ऐसी सूची होती है जिसे इंटरैक्ट किया जा सकता है और ड्रैग किया जा सकता है. इसका इस्तेमाल आपको बाद के चरण में करना होगा. फ़िलहाल, ZStack
के अंदर MapViewControllerBridge
को ZStack
के पहले चाइल्ड व्यू के तौर पर बनाएं, ताकि शहरों की सूची के पीछे ऐप्लिकेशन में मैप दिखे. ऐसा करने पर, ContentView
में मौजूद body
प्रॉपर्टी का कॉन्टेंट ऐसा दिखना चाहिए:
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()
} // ...
}
}
}
- अब ऐप्लिकेशन चलाएं. अब आपको अपने डिवाइस की स्क्रीन पर मैप लोड होता हुआ दिखेगा. साथ ही, स्क्रीन पर सबसे नीचे शहरों की एक ऐसी सूची दिखेगी जिसे खींचकर ऊपर-नीचे किया जा सकता है.
7. मैप में मार्कर जोड़ना
पिछले चरण में, आपने शहरों की सूची दिखाने वाले इंटरैक्टिव मैप को जोड़ा था. इस सेक्शन में, आपको सूची में मौजूद हर शहर के लिए मार्कर जोड़ने होंगे.
मार्कर को राज्य के तौर पर इस्तेमाल करना
ContentView
, markers
नाम की एक प्रॉपर्टी का एलान करता है. यह GMSMarker
की एक सूची है. इसमें cities
स्टैटिक प्रॉपर्टी में एलान किए गए हर शहर को दिखाया गया है. ध्यान दें कि इस प्रॉपर्टी को SwiftUI प्रॉपर्टी रैपर State के साथ एनोटेट किया गया है. इससे पता चलता है कि इसे SwiftUI मैनेज करेगा. इसलिए, अगर इस प्रॉपर्टी में कोई बदलाव होता है, जैसे कि मार्कर जोड़ना या हटाना, तो इस स्थिति का इस्तेमाल करने वाले व्यू अपडेट हो जाएंगे.
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
}
ध्यान दें कि ContentView
, शहरों की सूची को रेंडर करने के लिए markers
प्रॉपर्टी का इस्तेमाल करता है. इसके लिए, वह इस प्रॉपर्टी को 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)
}
}
}
}
@Binding
का इस्तेमाल करके, MapViewControllerBridge को State पास करें
markers
प्रॉपर्टी से डेटा दिखाने वाले शहरों की सूची के अलावा, इस प्रॉपर्टी को MapViewControllerBridge
स्ट्रक्ट में पास करें, ताकि इसका इस्तेमाल मैप पर उन मार्कर को दिखाने के लिए किया जा सके. ऐसा करने के लिए:
MapViewControllerBridge
में नईmarkers
प्रॉपर्टी का एलान करें, जिसमें@Binding
एनोटेशन जोड़ा गया हो
MapViewControllerBridge
struct MapViewControllerBridge: : UIViewControllerRepresentable {
@Binding var markers: [GMSMarker]
// ...
}
MapViewControllerBridge
में,markers
प्रॉपर्टी का इस्तेमाल करने के लिए,updateUIViewController(_, context)
तरीका अपडेट करें
पिछले चरण में बताया गया है कि जब भी स्थिति में बदलाव होगा, तब SwiftUI, updateUIViewController(_, context)
को कॉल करेगा. हमें इस तरीके में मैप को अपडेट करना है, ताकि markers
में मार्कर दिखें. इसके लिए, आपको हर मार्कर की map
प्रॉपर्टी को अपडेट करना होगा. यह चरण पूरा करने के बाद, आपका MapViewControllerBridge
ऐसा दिखना चाहिए:
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 }
}
}
markers
प्रॉपर्टी कोContentView
सेMapViewControllerBridge
में पास करें
आपने MapViewControllerBridge
में एक नई प्रॉपर्टी जोड़ी है. इसलिए, अब इस प्रॉपर्टी की वैल्यू को MapViewControllerBridge
के इनिशियलाइज़र में पास करना ज़रूरी है. इसलिए, अगर ऐप्लिकेशन बनाने की कोशिश की जाती है, तो आपको दिखेगा कि यह कंपाइल नहीं होगा. इस समस्या को ठीक करने के लिए, ContentView
में अपडेट करें. यहां MapViewControllerBridge
बनाया गया है और markers
प्रॉपर्टी को इस तरह पास करें:
struct ContentView: View {
// ...
var body: some View {
// ...
GeometryReader { geometry in
ZStack(alignment: .top) {
// Map
MapViewControllerBridge(markers: $markers)
// ...
}
}
}
}
ध्यान दें कि $
प्रीफ़िक्स का इस्तेमाल, markers
को MapViewControllerBridge
में पास करने के लिए किया गया था. ऐसा इसलिए, क्योंकि यह एक बाउंड प्रॉपर्टी की उम्मीद करता है. $
, Swift प्रॉपर्टी रैपर के साथ इस्तेमाल करने के लिए रिज़र्व किया गया प्रीफ़िक्स है. किसी स्टेट पर लागू करने पर, यह Binding दिखाता है.
- अब ऐप्लिकेशन चलाकर देखें कि मैप पर मार्कर दिख रहे हैं या नहीं.
8. चुने गए शहर पर ऐनिमेशन दिखाना
पिछले चरण में, आपने एक SwiftUI व्यू से दूसरे SwiftUI व्यू में राज्य की जानकारी भेजकर, मैप में मार्कर जोड़े थे. इस चरण में, इंटरैक्ट की जा सकने वाली सूची में किसी शहर या मार्कर पर टैप करने के बाद, उसे ऐनिमेट किया जाएगा. ऐनिमेशन बनाने के लिए, आपको किसी स्टेट में हुए बदलावों पर प्रतिक्रिया देनी होगी. इसके लिए, बदलाव होने पर मैप की कैमरा पोज़िशन में बदलाव करें. मैप के कैमरे के कॉन्सेप्ट के बारे में ज़्यादा जानने के लिए, कैमरा और व्यू देखें.
मैप को चुने गए शहर पर ऐनिमेट करें
मैप को किसी चुने गए शहर पर ऐनिमेट करने के लिए:
MapViewControllerBridge
में नया बाइंडिंग तय करना
ContentView
में selectedMarker
नाम की एक स्टेट प्रॉपर्टी है. इसे शून्य पर सेट किया गया है. जब भी सूची में कोई शहर चुना जाता है, तब यह अपडेट हो जाती है. इसे ContentView
में मौजूद CitiesList
व्यू buttonAction
मैनेज करता है.
ContentView
CitiesList(markers: $markers) { (marker) in
guard self.selectedMarker != marker else { return }
self.selectedMarker = marker
// ...
}
जब भी selectedMarker
में बदलाव होता है, तो MapViewControllerBridge
को इस बदलाव के बारे में पता होना चाहिए, ताकि वह मैप को चुने गए मार्कर पर ऐनिमेशन के साथ दिखा सके. इसलिए, GMSMarker
टाइप का नया Binding, MapViewControllerBridge
में तय करें और प्रॉपर्टी का नाम selectedMarker
रखें.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
@Binding var selectedMarker: GMSMarker?
}
selectedMarker
में बदलाव होने पर, मैप को ऐनिमेट करने के लिएMapViewControllerBridge
को अपडेट करें
नया बाइंडिंग घोषित होने के बाद, आपको MapViewControllerBridge
के updateUIViewController_, context)
फ़ंक्शन को अपडेट करना होगा, ताकि मैप चुने गए मार्कर पर ऐनिमेट हो सके. इसके लिए, यहां दिए गए कोड को कॉपी करें:
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)
})
}
}
}
}
}
animateToSelectedMarker(viewController)
फ़ंक्शन, GMSMapView
के animate(with)
फ़ंक्शन का इस्तेमाल करके, मैप के ऐनिमेशन का क्रम दिखाएगा.
ContentView
काselectedMarker
,MapViewControllerBridge
को पास करें
MapViewControllerBridge
में नया बाइंडिंग एलान होने के बाद, ContentView
को अपडेट करें, ताकि selectedMarker
में MapViewControllerBridge
को इंस्टैंशिएट किया जा सके.
ContentView
struct ContentView: View {
// ...
var body: some View {
// ...
GeometryReader { geometry in
ZStack(alignment: .top) {
// Map
MapViewControllerBridge(markers: $markers, selectedMarker: $selectedMarker)
// ...
}
}
}
}
इस चरण को पूरा करने के बाद, सूची में कोई नया शहर चुनने पर मैप में ऐनिमेशन दिखेगा.
शहर पर ज़ोर देने के लिए, SwiftUI व्यू को ऐनिमेट करना
SwiftUI, व्यू को ऐनिमेट करने की प्रोसेस को आसान बनाता है. ऐसा इसलिए, क्योंकि यह स्टेट ट्रांज़िशन के लिए ऐनिमेशन को मैनेज करता है. इसे दिखाने के लिए, मैप ऐनिमेशन पूरा होने के बाद, चुनी गई सिटी पर व्यू को फ़ोकस करके ज़्यादा ऐनिमेशन जोड़े जाएंगे. ऐसा करने के लिए, यहां दिया गया तरीका अपनाएं:
MapViewControllerBridge
मेंonAnimationEnded
क्लोज़र जोड़ना
SwiftUI ऐनिमेशन, मैप ऐनिमेशन के उस क्रम के बाद होगा जिसे आपने पहले जोड़ा था. इसलिए, MapViewControllerBridge
के अंदर onAnimationEnded
नाम का एक नया क्लोज़र घोषित करें. साथ ही, animateToSelectedMarker(viewController)
तरीके के अंदर, मैप ऐनिमेशन के खत्म होने के 0.5 सेकंड बाद इस क्लोज़र को शुरू करें.
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()
})
})
}
}
}
}
}
MapViewControllerBridge
मेंonAnimationEnded
लागू करना
onAnimationEnded
क्लोज़र को लागू करें, जहां MapViewControllerBridge
को ContentView
में इंस्टैंशिएट किया गया है. नीचे दिए गए कोड को कॉपी करें और चिपकाएं. यह कोड zoomInCenter
नाम का एक नया स्टेट जोड़ता है. साथ ही, यह clipShape
का इस्तेमाल करके व्यू में बदलाव करता है और 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))
}
}
}
}
- ऐनिमेशन देखने के लिए, ऐप्लिकेशन चलाएं!
9. SwiftUI को इवेंट भेजना
इस चरण में, आपको GMSMapView
से भेजे गए इवेंट सुनने होंगे. साथ ही, उस इवेंट को SwiftUI पर भेजना होगा. खास तौर पर, आपको मैप व्यू के लिए एक डेलिगेट सेट करना होगा. साथ ही, कैमरे के मूव होने से जुड़े इवेंट सुनने होंगे. इससे, जब किसी शहर पर फ़ोकस किया जाएगा और मैप का कैमरा किसी जेस्चर से मूव होगा, तो मैप व्यू अनफ़ोकस हो जाएगा. इससे आपको मैप का ज़्यादा हिस्सा दिखेगा.
SwiftUI कोऑर्डिनेटर का इस्तेमाल करना
GMSMapView
, कैमरे की पोज़िशन में बदलाव या मार्कर पर टैप करने जैसे इवेंट जनरेट करता है. इन इवेंट को सुनने का तरीका, GMSMapViewDelegate प्रोटोकॉल के ज़रिए होता है. SwiftUI, Coordinator का कॉन्सेप्ट पेश करता है. इसका इस्तेमाल खास तौर पर, UIKit व्यू कंट्रोलर के लिए डेलिगेट के तौर पर काम करने के लिए किया जाता है. इसलिए, SwiftUI में Coordinator को GMSMapViewDelegate
प्रोटोकॉल के मुताबिक काम करना चाहिए. इसके लिए, यह तरीका अपनाएं:
MapViewControllerBridge
मेंMapViewCoordinator
नाम का कोऑर्डिनेटर बनाएं
MapViewControllerBridge
क्लास में एक नेस्ट की गई क्लास बनाएं और उसे MapViewCoordinator
नाम दें. इस क्लास को GMSMapViewDelegate
के मुताबिक होना चाहिए. साथ ही, इसे MapViewControllerBridge
को प्रॉपर्टी के तौर पर एलान करना चाहिए.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
// ...
final class MapViewCoordinator: NSObject, GMSMapViewDelegate {
var mapViewControllerBridge: MapViewControllerBridge
init(_ mapViewControllerBridge: MapViewControllerBridge) {
self.mapViewControllerBridge = mapViewControllerBridge
}
}
}
MapViewControllerBridge
मेंmakeCoordinator()
लागू करना
इसके बाद, MapViewControllerBridge
में makeCoordinator()
तरीके को लागू करें और पिछले चरण में बनाए गए MapViewCoodinator
का एक इंस्टेंस वापस पाएं.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
// ...
func makeCoordinator() -> MapViewCoordinator {
return MapViewCoordinator(self)
}
}
MapViewCoordinator
को मैप व्यू के डेलिगेट के तौर पर सेट करें
कस्टम कोऑर्डिनेटर बनाने के बाद, अगला चरण कोऑर्डिनेटर को व्यू कंट्रोलर के मैप व्यू के लिए डेलिगेट के तौर पर सेट करना है. इसके लिए, makeUIViewController(context)
में व्यू कंट्रोलर के इनिशियलाइज़ेशन को अपडेट करें. पिछले चरण में बनाया गया कोऑर्डिनेटर, कॉन्टेक्स्ट ऑब्जेक्ट से ऐक्सेस किया जा सकेगा.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
// ...
func makeUIViewController(context: Context) -> MapViewController {
let uiViewController = MapViewController()
uiViewController.map.delegate = context.coordinator
return uiViewController
}
}
MapViewControllerBridge
में क्लोज़र जोड़ें, ताकि कैमरे के हिलने से जुड़ा इवेंट ऊपर की ओर भेजा जा सके
कैमरे की गतिविधियों के हिसाब से व्यू को अपडेट करने के लिए, एक नई क्लोज़र प्रॉपर्टी का एलान करें. यह MapViewControllerBridge
में बूलियन वैल्यू स्वीकार करती है. इसे mapViewWillMove
कहा जाता है. साथ ही, इस क्लोज़र को डेलिगेट तरीके mapView(_, willMove)
में MapViewCoordinator
के अंदर लागू करें. gesture
की वैल्यू को क्लोज़र में पास करें, ताकि SwiftUI व्यू सिर्फ़ कैमरे को हिलाने से जुड़े जेस्चर वाले इवेंट पर प्रतिक्रिया दे सके.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
var mapViewWillMove: (Bool) -> ()
//...
final class MapViewCoordinator: NSObject, GMSMapViewDelegate {
// ...
func mapView(_ mapView: GMSMapView, willMove gesture: Bool) {
self.mapViewControllerBridge.mapViewWillMove(gesture)
}
}
}
mapWillMove
के लिए वैल्यू पास करने के लिए, ContentView को अपडेट करें
MapViewControllerBridge
को कारोबार बंद होने की नई तारीख के बारे में एलान किया गया है. इसलिए, ContentView
को अपडेट करें, ताकि कारोबार बंद होने की नई तारीख की वैल्यू पास की जा सके. अगर मूव इवेंट किसी जेस्चर से जुड़ा है, तो बंद करने के उस तरीके में, स्टेट zoomInCenter
को false
पर टॉगल करें. इससे मैप को जेस्चर से हिलाने पर, वह फिर से फ़ुल व्यू में दिखेगा.
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
})
// ...
}
}
}
}
- नए बदलाव देखने के लिए, ऐप्लिकेशन को चलाएं!
10. बधाई हो
यहां तक पहुंचने के लिए बधाई! आपने काफ़ी कुछ सीख लिया है. हमें उम्मीद है कि अब आपको iOS के लिए Maps SDK का इस्तेमाल करके, अपना SwiftUI ऐप्लिकेशन बनाने में मदद मिलेगी.
आपने क्या सीखा
- SwiftUI और UIKit में अंतर
- UIViewControllerRepresentable का इस्तेमाल करके, SwiftUI और UIKit के बीच ब्रिज बनाने का तरीका
- State और Binding की मदद से, मैप व्यू में बदलाव करने का तरीका
- Coordinator का इस्तेमाल करके, मैप व्यू से SwiftUI को इवेंट भेजने का तरीका
आगे क्या करना है?
- iOS के लिए Maps SDK
- iOS के लिए Maps SDK का आधिकारिक दस्तावेज़
- Places SDK for iOS - अपने आस-पास के स्थानीय कारोबारों और दिलचस्पी की जगहों के बारे में जानकारी पाना
- maps-sdk-for-ios-samples
- GitHub पर सैंपल कोड, जिसमें iOS के लिए Maps SDK की सभी सुविधाओं के बारे में बताया गया है.
- SwiftUI - SwiftUI के बारे में Apple का आधिकारिक दस्तावेज़
- नीचे दिए गए सर्वे के सवालों के जवाब दें, ताकि हम आपके लिए सबसे काम का कॉन्टेंट बना सकें:
आपको और कौनसे कोडलैब देखने हैं?
क्या आपको अपनी पसंद का कोडलैब नहीं मिल रहा है? यहां नई समस्या के साथ इसका अनुरोध करें.