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