1. לפני שתתחיל
בשיעור הזה תלמדו איך להתחיל להשתמש בפלטפורמת מפות Google כדי ליצור אפליקציות ל-iOS ב-Swift. תבנו אפליקציית iOS שתבצע את הפעולות הבאות:
- טוען את Maps SDK ל-iOS ואת ספריית כלי העזר של Maps SDK ל-iOS.
- מוצגת מפה שמרכזה בסידני, אוסטרליה.
- הצגת סמנים מותאמים אישית ל-100 נקודות מסביב לסידני.
- מטמיע קיבוץ של סמנים.
- מאפשר אינטראקציה של משתמש שמרכזת מחדש את המפה ומציירת עיגול במפה כשמקישים על סמן.
דרישות מוקדמות
- ידע בסיסי ב-Swift ובפיתוח אפליקציות ל-iOS.
הפעולות שתבצעו:
- טוענים את Maps SDK ל-iOS ואת Google Maps SDK ל-iOS Utility Library.
- טוענים מפה.
- שימוש בסמנים, בסמנים בהתאמה אישית ובקיבוץ סמנים.
- כדי לתמוך באינטראקציות של משתמשים, צריך להשתמש במערכת האירועים של Maps SDK for iOS.
- שליטה במצלמת המפה באופן פרוגרמטי.
- מציירים על המפה.
מה נדרש
כדי להשלים את ה-codelab הזה, תצטרכו את החשבונות, השירותים והכלים הבאים:
- Xcode 12.0 ואילך עם SDK יעד מגרסה 12.0 ואילך.
- Cocoapods מותקן.
- חשבון ב-Google Cloud Platform עם חיוב מופעל (ראו את השלב הבא).
- פרויקט ב-Cloud Console שבו מופעל SDK של מפות ל-iOS (ראו את השלב הבא).
2. להגדרה
בשלב ההפעלה שבהמשך, צריך להפעיל את Maps SDK ל-iOS.
הגדרת הפלטפורמה של מפות Google
אם עדיין אין לכם חשבון ב-Google Cloud Platform ופרויקט עם חיוב מופעל, תוכלו לעיין במדריך תחילת העבודה עם הפלטפורמה של מפות Google כדי ליצור חשבון לחיוב ופרויקט.
- בCloud Console, לוחצים על התפריט הנפתח של הפרויקט ובוחרים את הפרויקט שבו רוצים להשתמש ב-codelab הזה.
- מפעילים ב-Google Cloud Marketplace את ממשקי ה-API וערכות ה-SDK של הפלטפורמה של מפות Google שנדרשים ל-codelab הזה. כדי לעשות זאת, פועלים לפי השלבים בסרטון הזה או בתיעוד הזה.
- יוצרים מפתח API בדף Credentials במסוף Cloud. אפשר לפעול לפי השלבים שמפורטים בסרטון הזה או בתיעוד הזה. כל הבקשות אל הפלטפורמה של מפות Google מחייבות מפתח API.
מדריך למתחילים
כדי לעזור לכם להתחיל כמה שיותר מהר, הנה קוד התחלתי שיעזור לכם לעקוב אחרי ההוראות במעבדת התכנות הזו.
- משכפלים את המאגר אם
git
מותקן.
git clone https://github.com/googlemaps/codelab-maps-platform-101-swift.git
אפשר גם ללחוץ על Give me the code (תביא לי את הקוד) כדי להוריד את קוד המקור.
- אחרי שמורידים את הקוד, פותחים את הפרויקט StarterApp בספרייה
/starter
. הפרויקט הזה כולל את מבנה הקבצים הבסיסי שצריך כדי להשלים את ה-codelab. כל מה שצריך לעבודה נמצא בספרייה/starter/StarterApp
.
כדי לראות את הקוד המלא של הפתרון, אפשר לעיין בקוד המלא בספרייה /solution/SolutionApp
.
3. התקנה של Maps SDK ל-iOS
השלב הראשון בשימוש ב-Maps SDK ל-iOS הוא התקנת התלויות הנדרשות. התהליך הזה כולל שני שלבים: התקנת Maps SDK ל-iOS וספריית כלי השירות של Maps SDK ל-iOS ממנהל התלות של Cocoapods, ומתן מפתח ה-API ל-SDK.
- מוסיפים את Maps SDK ל-iOS ואת Maps SDK ל-iOS Utility Library אל
Podfile
.
ב-codelab הזה נעשה שימוש ב-SDK של מפות ל-iOS, שמספק את כל הפונקציונליות העיקרית של מפות Google, ובספריית כלי השירות של מפות ל-iOS, שמספקת מגוון כלי שירות להעשרת המפה, כולל אשכולות של סמנים.
כדי להתחיל, פותחים את Podfile
ב-Xcode (או בעורך הטקסט המועדף) ומעדכנים את הקובץ כך שיכלול את התלות של Maps SDK ל-iOS ושל ספריית כלי העזר מתחת להערה # Pods for StarterApp
:
pod 'GoogleMaps', '6.1.0' pod 'Google-Maps-iOS-Utils', '3.4.0'
במסמכי התיעוד של Maps SDK ל-iOS Versions אפשר למצוא את הגרסה העדכנית של ה-SDK והנחיות לתחזוקה.
התג Podfile
אמור להיראות כך:
source 'https://github.com/CocoaPods/Specs.git' platform :ios, '12.0' target 'StarterApp' do # Comment the next line if you don't want to use dynamic frameworks use_frameworks! # Pods for StarterApp pod 'GoogleMaps', '6.1.0' pod 'Google-Maps-iOS-Utils', '3.4.0' end
- מתקינים את Maps SDK ל-iOS ואת Maps SDK ל-iOS Utility Library pods.
כדי להתקין את יחסי התלות, מריצים את הפקודה pod install
בספרייה /starter
משורת הפקודה. Cocoapods מוריד באופן אוטומטי את קשרי התלות ויוצר את StarterApp.xcworkspace
.
- אחרי שמתקינים את התלויות, מריצים את הפקודה
open StarterApp.xcworkspace
מהספרייה/starter
כדי לפתוח את הקובץ ב-Xcode, ואז מריצים את האפליקציה בסימולטור של אייפון על ידי לחיצה עלCommand+R
. אם הכול מוגדר בצורה נכונה, הסימולטור יופעל ויוצג מסך שחור. אל דאגה, עדיין לא יצרת כלום, אז זה צפוי! - מייבאים את ה-SDK ב-
AppDelegate.swift
.
אחרי שמתקינים את יחסי התלות, צריך לספק את מפתח ה-API ל-SDK. השלב הראשון הוא לייבא את Maps SDK ל-iOS כתלות על ידי הוספת השורה הבאה מתחת לimport UIKit
הצהרת הייבוא:
import GoogleMaps
- מעבירים את מפתח ה-API אל iOS SDK על ידי הפעלת
provideAPIKey
ב-GMSServices
ב-application: didFinishLaunchingWithOptions:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
GMSServices.provideAPIKey("YOUR_API_KEY")
return true
}
קובץ AppDelegate.swift
המעודכן אמור להיראות כך:
import UIKit
import GoogleMaps
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
GMSServices.provideAPIKey("YOUR_API_KEY")
return true
}
}
מחליפים את YOUR_API_KEY
במפתח ה-API שיצרתם במסוף Cloud.
אחרי שהתקנתם את התלויות וסיפקתם את מפתח ה-API, אתם יכולים להתחיל לבצע קריאות ל-Maps SDK ל-iOS.
4. הצגת מפה
הגיע הזמן להציג את המפה הראשונה!
החלק הנפוץ ביותר ב-Maps SDK ל-iOS הוא המחלקה GMSMapView
, שמספקת רבות מהשיטות שמאפשרות ליצור מופעים של מפות ולבצע בהם מניפולציות. כך עושים זאת:
- פתיחת
ViewController.swift
.
כאן תבצעו את שאר העבודה בסדנת הקוד הזו. שימו לב: אירועי מחזור החיים של בקר התצוגה loadView
ו-viewDidLoad
כבר מוגדרים בשבילכם.
- כדי לייבא את Maps SDK ל-iOS, מוסיפים את השורה הבאה בחלק העליון של הקובץ:
import GoogleMaps
- מצהירים על משתנה מופע
ViewController
כדי לאחסן אתGMSMapView
.
המופע של GMSMapView
הוא האובייקט העיקרי שאתם עובדים איתו לאורך ה-Codelab הזה, ותתייחסו אליו ותפעלו אותו משיטות שונות של מחזור החיים של בקר התצוגה. כדי להפוך אותו לזמין, צריך לעדכן את ההטמעה של ViewController
כדי להצהיר על משתנה מופע לאחסון שלו:
class ViewController: UIViewController {
private var mapView: GMSMapView!
...
}
- ב-
loadView
, יוצרים מופע שלGMSCameraPosition
.
GMSCameraPosition
מגדיר את המיקום של מרכז המפה ואת רמת הזום שמוצגת. הקוד הזה קורא לשיטה cameraWithLatitude:longitude:zoom:
כדי למרכז את המפה בסידני, אוסטרליה, בקו רוחב של -33.86 וקו אורך של 151.20, עם רמת זום של 12:
let camera:GMSCameraPosition = GMSCameraPosition.camera(withLatitude: -33.86, longitude: 151.20, zoom: 12)
- ב-
loadView
, יוצרים מופע שלGMSMapView
כדי ליצור מופע של המפה.
כדי ליצור מופע חדש של מפה, קוראים ל-GMSMapView(frame: CGRect, camera: GMSCameraPosition)
. שימו לב שהמסגרת מוגדרת ל-CGRect.zero
, שהוא משתנה גלובלי מספריית CGGeometry
של iOS שמציין מסגרת עם רוחב 0, גובה 0, שממוקמת במיקום (0,0) בתוך בקר התצוגה. המצלמה מוגדרת למיקום המצלמה שיצרתם.
לאחר מכן, כדי להציג את המפה, מגדירים את תצוגת הבסיס של בקר התצוגה ל-mapView
, וכך המפה מוצגת במסך מלא.
mapView = GMSMapView(frame: .zero, camera: camera)
self.view = mapView
- מגדירים את
GMSMapViewDelegate
לבקר התצוגה.
כשמטמיעים את הפונקציה הזו, היא מאפשרת לכם לטפל באירועים מאינטראקציות של משתמשים במופע GMSMapView
, שתצטרכו בהמשך.
קודם צריך לעדכן את הממשק של ViewController
כך שיתאים לפרוטוקול של GMSMapViewDelegate:
class ViewController: UIViewController, GMSMapViewDelegate
לאחר מכן, מוסיפים את השורה הבאה בפונקציה loadView
כדי להגדיר את GMSMapViewDelegate
ל-ViewController
.
mapView.delegate = self
עכשיו טוענים מחדש את האפליקציה בסימולטור iOS (Command+R
), והמפה אמורה להופיע כמו בצילום המסך הבא:
איור 1. אפליקציית iOS שמציגה מפה של Google.
לסיכום, בשלב הזה יצרתם מופע של GMSMapView
כדי להציג מפה שממורכזת על העיר סידני באוסטרליה.
קובץ ViewController.swift
אמור להיראות עכשיו כך:
import UIKit
import GoogleMaps
class ViewController: UIViewController, GMSMapViewDelegate {
private var mapView: GMSMapView!
override func loadView() {
// Load the map at set latitude/longitude and zoom level
let camera:GMSCameraPosition = GMSCameraPosition.camera(withLatitude: -33.86, longitude: 151.20, zoom: 11)
mapView = GMSMapView(frame: .zero, camera: camera)
self.view = mapView
mapView.delegate = self
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
5. עיצוב המפה (אופציונלי)
אתם יכולים להתאים אישית את הסגנון של המפה באמצעות עיצוב מפות מבוסס-ענן.
יצירת מזהה מפה
אם עדיין לא יצרתם מזהה מפה עם סגנון מפה שמשויך אליו, כדאי לעיין במדריך בנושא מזהי מפה כדי לבצע את השלבים הבאים:
- יוצרים מזהה מפה.
- משייכים מזהה מפה לסגנון מפה.
הוספת מזהה המפה לאפליקציה
כדי להשתמש במזהה המפה שיצרתם בשלב הקודם, פותחים את הקובץ ViewController.swift
ובתוך ה-method loadView
יוצרים אובייקט GMSMapID
ומזינים בו את מזהה המפה. לאחר מכן, משנים את יצירת המופע של GMSMapView
על ידי ציון האובייקט GMSMapID
כפרמטר.
ViewController.swift
override func loadView() {
// Load the map at set latitude/longitude and zoom level
let camera:GMSCameraPosition = GMSCameraPosition.camera(withLatitude: -33.86, longitude: 151.20, zoom: 11)
let mapID = GMSMapID(identifier: "YOUR_MAP_ID")
mapView = GMSMapView(frame: .zero, mapID: mapID, camera: camera)
self.view = mapView
mapView.delegate = self
}
אחרי שמסיימים את הפעולות האלה, מריצים את האפליקציה כדי לראות את המפה בסגנון שבחרתם.
6. הוספת סמנים למפה
יש הרבה דברים שמפתחים עושים באמצעות Maps SDK ל-iOS, אבל הצבת סמנים במפה היא ללא ספק הפעולה הפופולרית ביותר. סמנים מציגים נקודות ספציפיות במפה, והם רכיב נפוץ בממשק המשתמש לטיפול באינטראקציות של משתמשים. אם השתמשתם בעבר במפות Google, אתם כנראה מכירים את סמן ברירת המחדל, שנראה כמו הסיכות האדומות באיור 2:
איור 2. מפה עם סמנים אדומים.
בשלב הזה נראה איך להשתמש במחלקה GMSMarker
כדי להציב סמנים במפה.
שימו לב: אי אפשר להציב סמנים במפה עד שהמפה נטענת מהשלב הקודם באירוע מחזור החיים של בקר התצוגה loadView
. לכן, צריך להשלים את השלבים האלה באירוע מחזור החיים viewDidLoad
, שמופעל אחרי שהתצוגה (והמפה) נטענות.
- מגדירים אובייקט
CLLocationCoordinate2D
.
CLLocationCoordinate2D
הוא מבנה שזמין בספריית CoreLocation של iOS, שמגדיר מיקום גיאוגרפי בקו רוחב ובקו אורך מסוימים. כדי להתחיל ליצור את הסמן הראשון, מגדירים אובייקט CLLocationCoordinate2D
ומגדירים את קו הרוחב וקו האורך למרכז המפה. הקואורדינטות של מרכז המפה נגישות מתצוגת המפה באמצעות המאפיינים camera.target.latitude
ו-camera.target.longitude
.
// Add a single marker with a custom icon
let mapCenter = CLLocationCoordinate2DMake(mapView.camera.target.latitude, mapView.camera.target.longitude)
- ליצור מופע של
GMSMarker
.
Maps SDK ל-iOS מספק את המחלקה GMSMarker
. כל מופע של GMSMarker
מייצג סמן בודד במפה, והוא נוצר על ידי קריאה ל-markerWithPosition:
והעברת אובייקט CLLocationCoordinate2D
כדי לציין ל-SDK איפה למקם את הסמן במפה.
let marker = GMSMarker(position: mapCenter)
- הגדרת סמל מותאם אישית לסמן.
סמן הנעץ האדום שמופיע כברירת מחדל במפות Google הוא מצוין, אבל גם התאמה אישית של המפה היא אפשרות טובה. למזלכם, השימוש בסמן מותאם אישית הוא פשוט באמצעות Maps SDK ל-iOS. שימו לב שהפרויקט StarterApp כולל תמונה בשם custom_pin.png שתוכלו להשתמש בה, אבל אתם יכולים להשתמש בכל תמונה שתרצו.
כדי להגדיר את הסמן המותאם אישית, מגדירים את מאפיין icon
של הסמן למופע של UIImage
.
marker.icon = UIImage(named: "custom_pin.png")
- מעבדים את הסמן במפה.
הסמן נוצר, אבל הוא עדיין לא מופיע במפה. כדי לעשות זאת, מגדירים את המאפיין map
של מופע GMSMarker
למופע של GMSMapView
.
marker.map = mapView
עכשיו טוענים מחדש את האפליקציה ורואים את המפה הראשונה עם סמן, כמו שמוצג באיור 3.
איור 3. אפליקציית iOS עם מפות Google וסמן אדום במרכז.
לסיכום, בקטע הזה יצרתם מופע של המחלקה GMSMarker והחלתם אותו על תצוגת המפה כדי להציג סמן במפה. האירוע המעודכן במחזור החיים של viewDidLoad ב-ViewController.swift
אמור להיראות כך:
override func viewDidLoad() {
super.viewDidLoad()
// Add a single marker with a custom icon
let mapCenter = CLLocationCoordinate2DMake(mapView.camera.target.latitude, mapView.camera.target.longitude)
let marker = GMSMarker(position: mapCenter)
marker.icon = UIImage(named: "custom_pin.png")
marker.map = mapView
}
7. הפעלת קיבוץ סמנים
אם אתם משתמשים בהרבה סמנים, או אם הסמנים קרובים זה לזה, יכול להיות שתיתקלו בבעיה שבה הסמנים חופפים או צפופים מדי, מה שפוגע בחוויית המשתמש. לדוגמה, אם שני סמנים קרובים מאוד זה לזה, יכול להיות שתיווצר סיטואציה כמו זו שמוצגת באיור 4:
איור 4. שני סמנים קרובים מאוד זה לזה.
כאן נכנס לתמונה מקבץ סמנים. תכונה נפוצה נוספת היא קיבוץ סמנים, שמאפשר לקבץ סמנים סמוכים לסמל יחיד שמשתנה בהתאם לרמת הזום, כמו שמוצג באיור 5:
איור 5. דוגמה לסמנים שמקובצים לסמל אחד.
האלגוריתם של קיבוץ סמנים מחלק את האזור הגלוי במפה לרשת, ואז מקבץ סמלים שנמצאים באותה משבצת. צוות הפלטפורמה של מפות Google יצר ספריית כלי עזר שימושית בקוד פתוח בשם Google Maps SDK for iOS Utility Library. בין היתר, הספרייה הזו מטפלת באשכולות של סמנים באופן אוטומטי. מידע נוסף על קיבוץ סמנים זמין במסמכי התיעוד של הפלטפורמה של מפות Google. אפשר גם לעיין בקוד המקור של ספריית כלי השירות ל-iOS ב-GitHub.
- מוסיפים עוד סמנים למפה.
כדי לראות את התכונה של קיבוץ סמנים בפעולה, צריך להוסיף למפה הרבה סמנים. כדי לייעל את התהליך, אפשר להשתמש בכלי ליצירת סמנים שמופיע בפרויקט המתחיל ב-MarkerGenerator.swift
.
כדי להוסיף מספר מסוים של סמנים למפה, קוראים ל-MarkerGenerator(near:count:).markerArray
במחזור החיים של viewDidLoad
של בקר התצוגה מתחת לקוד מהשלב הקודם. השיטה יוצרת את מספר הסמנים שצוין ב-count
במיקומים אקראיים סביב הקואורדינטות שצוינו באובייקט CLLocationCoordinate2D
. במקרה כזה, אפשר להעביר לו את המשתנה mapCenter
שיצרתם קודם. הסמנים מוחזרים ב-[GMSMarker]
.
// Generate many markers
let markerArray = MarkerGenerator(near: mapCenter, count: 100).markerArray
כדי לבדוק איך נראים כל כך הרבה סמנים, מוסיפים את השורות האלה אחרי ההגדרה של markerArray
ומריצים את האפליקציה. חשוב להוסיף הערה לשורות האלה לפני שעוברים לשלבים הבאים, שבהם משתמשים ב-Marker Clusterer כדי לנהל את התצוגה של הסמנים:
// Comment the following code out if using the marker clusterer
// to manage markers instead.
for marker in markerArray {
marker.map = mapView
}
- מייבאים את ספריית כלי העזר של Google Maps SDK ל-iOS.
כדי להוסיף את ספריית כלי השירות של מפות Google ל-iOS כתלות לפרויקט, מוסיפים את השורה הבאה לרשימת התלויות בחלק העליון של ViewController.swift
:
import GoogleMapsUtils
- מגדירים את התוסף MarkerClusterer.
כדי להשתמש ב-MarkerClusterer, צריך לספק שלושה דברים כדי להגדיר את אופן הפעולה שלו: אלגוריתם לאשכולות, מחולל סמלים ורכיב עיבוד תצוגה. האלגוריתם קובע את אופן ההתנהגות של אשכולות הסמנים, כמו המרחק בין הסמנים שייכללו באותו אשכול. מחולל הסמלים מספק את סמלי האשכולות לשימוש ברמות שונות של זום. רכיב ה-renderer מטפל ברינדור בפועל של סמלי האשכול במפה.
אם רוצים, אפשר לכתוב את כל ההגדרות האלה מאפס. לחלופין, ספריית כלי השירות של מפות Google ל-iOS מספקת הטמעות ברירת מחדל כדי להפוך את התהליך למהיר יותר. מוסיפים את השורות הבאות:
// Set up the cluster manager with a supplied icon generator and renderer.
let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
let iconGenerator = GMUDefaultClusterIconGenerator()
let renderer = GMUDefaultClusterRenderer(mapView: mapView, clusterIconGenerator: iconGenerator)
- ליצור מופע של
GMUClusterManager
.
GMUClusterManager
היא המחלקה שמטמיעה את האשכול של הסמנים באמצעות האלגוריתם, מחולל הסמלים והרכיב לעיבוד התמונה שציינתם. כדי ליצור את רכיב ה-renderer ולהפוך אותו לזמין בתצוגת המפה, קודם מוסיפים משתנה מופע להטמעה של ViewController
כדי לאחסן את מופע מנהל האשכולות:
class ViewController: UIViewController, GMSMapViewDelegate {
private var mapView: GMSMapView!
private var clusterManager: GMUClusterManager!
}
לאחר מכן, יוצרים את המופע של GMUClusterManager
באירוע מחזור החיים viewDidLoad
:
clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm, renderer: renderer)
- מוסיפים את הסמנים ומריצים את הכלי לאשכול סמנים.
אחרי שמגדירים את מופע marker clusterer, מעבירים למנהל האשכולים את מערך הסמנים שרוצים לאגד לאשכולות באמצעות קריאה ל-add(items:)
, ואז מריצים את ה-clusterer באמצעות קריאה ל-cluster
.
clusterManager.setMapDelegate(self)
clusterManager.add(markerArray)
clusterManager.cluster()
טוענים מחדש את האפליקציה, ועכשיו אמורים לראות הרבה סמנים שמקובצים בצורה מסודרת כמו בדוגמה שבאיור 6. אפשר להתנסות ברמות זום שונות על ידי צביטה וזום במפה, כדי לראות את אשכולות הסמנים משתנים כשמתקרבים או מתרחקים.
איור 6. אפליקציית iOS עם מפות Google וסמנים מקובצים.
לסיכום, בשלב הזה הגדרתם מופע של כלי לאיחוד סמנים מתוך ספריית כלי השירות של Google Maps SDK ל-iOS, ואז השתמשתם בו כדי לאחד 100 סמנים במפה. האירוע במחזור החיים viewDidLoad
ב-ViewController.swift
אמור להיראות עכשיו כך:
override func viewDidLoad() {
super.viewDidLoad()
// Add a single marker with a custom icon
let mapCenter = CLLocationCoordinate2DMake(mapView.camera.target.latitude, mapView.camera.target.longitude)
let marker = GMSMarker(position: mapCenter)
marker.icon = UIImage(named: "custom_pin.png")
marker.map = mapView
// Generate many markers
let markerArray = MarkerGenerator(near: mapCenter, count: 100).markerArray
// Comment the following code out if using the marker clusterer
// to manage markers instead.
// for marker in markerArray {
// marker.map = mapView
// }
// Set up the cluster manager with a supplied icon generator and renderer.
let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
let iconGenerator = GMUDefaultClusterIconGenerator()
let renderer = GMUDefaultClusterRenderer(mapView: mapView, clusterIconGenerator: iconGenerator)
clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm, renderer: renderer)
clusterManager.setMapDelegate(self)
clusterManager.add(markerArray)
clusterManager.cluster()
}
8. הוספת אינטראקציה של משתמש
עכשיו יש לכם מפה שנראית מצוין, עם סמנים ועם קיבוץ סמנים. בשלב הזה, מוסיפים עוד טיפול באינטראקציות של המשתמשים באמצעות GMSMapViewDelegate
, שהוגדר קודם לכן כבקר התצוגה, כדי לשפר את חוויית המשתמש במפה.
ערכת Maps SDK ל-iOS מספקת מערכת אירועים מקיפה שמיושמת באמצעות נציג תצוגת המפה, שכוללת מטפלי אירועים שמאפשרים להריץ קוד כשמתרחשות אינטראקציות שונות של משתמשים. לדוגמה, נציג MapView כולל שיטות שמאפשרות להפעיל ביצוע קוד לאינטראקציות, כמו קליק של המשתמש על המפה ועל סמנים, הזזה של תצוגת המפה, שינוי מרחק התצוגה ועוד.
בשלב הזה, מבצעים באופן פרוגרמטי הזזה של המפה כך שכל סמן שהמשתמש מקיש עליו יוצג במרכז.
- מטמיעים את ה-event listener של הקשה על סמן.
mapView(_:didTap:)
נקראת בכל פעם שהמשתמש מקיש על אחד מהסמנים שיצרתם קודם, ובכל פעם שהמשתמש מקיש על קבוצת סמנים (קבוצות סמנים מיושמות באופן פנימי כמופע של GMSMarker
).
כדי להטמיע את מאזין האירועים, מתחילים ביצירת stub שלו בתחתית ViewController.swift
לפני הסוגר המסולסל הסוגר.
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
return false
}
שימו לב שהשיטה מחזירה false
. הפעולה הזו אומרת ל-iOS SDK להמשיך להפעיל את התנהגות ברירת המחדל של GMSMarker
, כמו הצגת חלון מידע אם הוא מוגדר, אחרי הפעלת קוד ה-handler של האירוע.
- מטפלים באירוע ההקשה ומפעילים אנימציה של המצלמה כדי למרכז מחדש את המפה כשמקישים על סמן או על קבוצת סמנים.
כשמתקשרים אל mapView(_:didTap:)
, המופע של GMSMarker
שהוקש עליו מועבר כדי שתוכלו לטפל בו בקוד. אפשר להשתמש במופע הזה כדי למרכז מחדש את המפה על ידי קריאה ל-animate(toLocation:)
בתצוגת המפה מתוך handler האירועים, והעברת המיקום של מופע הסמן מהמאפיין position
.
// Animate to the marker
mapView.animate(toLocation: marker.position)
- הגדלת התצוגה של קבוצת סמנים כשמקישים עליה.
דפוס נפוץ של חוויית משתמש הוא הגדלה של קבוצות סמנים כשמקישים עליהן. כך המשתמשים יכולים לראות את הסמנים המקובצים, כי הקבוצה מתרחבת ברמות זום נמוכות יותר.
כפי שצוין קודם, סמל אשכול הסמנים הוא למעשה הטמעה של GMSMarker
עם סמל בהתאמה אישית. אז איך אפשר לדעת אם הקשה הייתה על סמן או על קבוצת סמנים? כשמנהל אשכולות הסמנים יוצר סמל אשכול חדש, הוא מטמיע את המופע של GMSMarker
בהתאם לפרוטוקול שנקרא GMUCluster.
אפשר להשתמש בתנאי כדי לבדוק אם הסמן שעבר ל-handler של האירוע תואם לפרוטוקול הזה.
אחרי שאתם יודעים באופן פרוגרמטי שלקלאסטר מסוים הייתה הקשה, אתם יכולים לקרוא ל-animate(toZoom:)
במופע של תצוגת המפה ולהגדיר את הזום לרמת הזום הנוכחית בתוספת אחת. רמת הזום הנוכחית זמינה במופע mapView במאפיין camera.zoom
.
שימו לב גם איך הקוד הבא מחזיר true
. ההוראה הזו אומרת למטפל באירועים שסיימתם לטפל באירוע, ושהוא לא צריך להריץ קוד נוסף במטפל. אחת מהסיבות לעשות את זה היא למנוע מהאובייקט הבסיסי GMSMarker
להפעיל את שאר התנהגויות ברירת המחדל שלו, כמו הצגת חלון מידע, שלא תהיה הגיונית במקרה של הקשה על סמל של צביר.
// If the tap was on a marker cluster, zoom in on the cluster
if let _ = marker.userData as? GMUCluster {
mapView.animate(toZoom: mapView.camera.zoom + 1)
return true
}
עכשיו טוענים מחדש את האפליקציה ומקישים על סמנים מסוימים ועל אשכולות של סמנים. כשמקישים על אחד מהם, המפה מתמרכזת מחדש על הרכיב שהוקש עליו. כשמקישים על קבוצת סמנים, המפה גם תבצע זום אין ברמה אחת, וקבוצת הסמנים תתרחב כדי להציג את הסמנים שמתחתיה.
לסיכום, בשלב הזה הטמעתם את פונקציית ה-event listener של הקשה על סמן, וטיפלתם באירוע כדי למרכז מחדש את התצוגה על האלמנט שהוקש עליו ולהגדיל את התצוגה אם האלמנט הזה הוא סמל של קבוצת סמנים.
השיטה mapView(_:didTap:)
אמורה להיראות כך:
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
// Animate to the marker
mapView.animate(toLocation: marker.position)
// If the tap was on a marker cluster, zoom in on the cluster
if let _ = marker.userData as? GMUCluster {
mapView.animate(toZoom: mapView.camera.zoom + 1)
return true
}
return false
}
9. ציור על המפה
עד עכשיו יצרתם מפה של סידני שמוצגים בה סמנים ב-100 נקודות אקראיות, וטיפלתם באינטראקציה של המשתמשים. בשלב האחרון של ה-codelab הזה, תשתמשו בתכונות הציור של Maps SDK for iOS כדי להוסיף תכונה שימושית נוספת לחוויית המפה שלכם.
תארו לעצמכם שהמשתמשים במפה הזו רוצים לגלות את העיר סידני. תכונה שימושית תהיה להציג רדיוס מסביב לסמן כשלוחצים עליו. כך המשתמש יוכל להבין במהירות אילו יעדים אחרים נמצאים במרחק קצר מהסמן שעליו הוא לחץ.
ה-SDK ל-iOS כולל קבוצה של פונקציות לשרטוט צורות במפה, כמו ריבועים, פוליגונים, קווים ומעגלים. בשלב הזה, צריך להציג עיגול כדי להראות רדיוס של 800 מטר (בערך חצי מייל) סביב סמן כשלוחצים עליו.
- מוסיפים משתנה מופע
circle
להטמעה של ViewController.
משתנה המופע הזה משמש לשמירת המעגל האחרון שצויר, כדי שאפשר יהיה להרוס אותו לפני שצויר מעגל אחר. בסופו של דבר, לא יהיה שימושי למשתמש ולא ייראה טוב אם כל סמן שהמשתמש יקיש עליו יוקף בעיגול.
כדי לעשות זאת, מעדכנים את ההטמעה של ViewController
באופן הבא:
class ViewController: UIViewController, GMSMapViewDelegate {
private var mapView: GMSMapView!
private var clusterManager: GMUClusterManager!
private var circle: GMSCircle? = nil
...
}
- לשרטט את העיגול כשמקישים על סמן.
בתחתית השיטה mapView(_:didTap:)
, ממש מעל ההצהרה return false
, מוסיפים את הקוד שמוצג כאן כדי ליצור מופע של המחלקה GMSCircle
של iOS SDK לצורך שרטוט של מעגל חדש ברדיוס של 800 מטרים על ידי קריאה ל-GMSCircle(position:radius:)
והעברת המיקום של הסמן שהקשתם עליו, כמו שעשיתם כשמרכזתם מחדש את המפה.
// Draw a new circle around the tapped marker
circle = GMSCircle(position: marker.position, radius: 800)
- מעצבים את המעגל.
כברירת מחדל, GMSCircle
מצייר עיגול עם קו שחור ומילוי שקוף. השיטה הזו מאפשרת להציג את הרדיוס, אבל היא לא נראית טוב וקצת קשה לראות אותו. לאחר מכן, נותנים לעיגול צבע מילוי כדי לשפר את הסגנון על ידי הקצאת UIColor
למאפיין fillColor
של העיגול. הקוד שמוצג כאן מוסיף מילוי אפור עם שקיפות של 50%:
circle?.fillColor = UIColor(red: 0.67, green: 0.67, blue: 0.67, alpha: 0.5)
- הצגת המעגל במפה.
בדומה ליצירת סמנים קודם לכן, יצירת מופע של GMSCircle
לא גורמת לו להופיע במפה. כדי לעשות זאת, מקצים את מופע תצוגת המפה למאפיין map
של העיגול.
circle?.map = mapView
- מסירים את כל המעגלים שנוצרו קודם.
כמו שציינו קודם, חוויית המשתמש לא תהיה טובה אם נמשיך להוסיף עיגולים למפה. כדי להסיר את העיגול שנוצר על ידי אירוע הקשה קודם, מגדירים את המאפיין map
של circle
ל-nil
בחלק העליון של mapView(_:didTap:)
.
// Clear previous circles
circle?.map = nil
טוענים מחדש את האפליקציה ומקישים על סמן. בכל פעם שמקישים על סמן, אמור להופיע עיגול חדש, וכל עיגול שצויר קודם אמור להיעלם, כמו שמוצג באיור 7.
איור 7. עיגול שמצויר מסביב לסמן שהקשתם עליו.
לסיכום, בשלב הזה השתמשתם במחלקה GMSCircle
כדי להציג עיגול בכל פעם שמקישים על סמן.
השיטה mapView(_:didTap:)
אמורה להיראות כך:
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
// Clear previous circles
circle?.map = nil
// Animate to the marker
mapView.animate(toLocation: marker.position)
// If the tap was on a marker cluster, zoom in on the cluster
if let _ = marker.userData as? GMUCluster {
mapView.animate(toZoom: mapView.camera.zoom + 1)
return true
}
// Draw a new circle around the tapped marker
circle = GMSCircle(position: marker.position, radius: 800)
circle?.fillColor = UIColor(red: 0.67, green: 0.67, blue: 0.67, alpha: 0.5)
circle?.map = mapView
return false
}
10. מזל טוב
יצרת בהצלחה אפליקציית iOS עם מפת Google אינטראקטיבית.
מה למדתם
- טעינה והגדרה של Maps SDK ל-iOS ושל Google Maps SDK ל-iOS Utility Library
- טעינה של מפה
- עיצוב מפה
- שימוש בסמנים, בסמנים מותאמים אישית ובקיבוץ סמנים
- מערכת האירועים כדי לספק אינטראקציה עם המשתמש
- שליטה במצלמת המפה באופן פרוגרמטי
- ציור על המפה
מה השלב הבא?
- כדי לקבל עוד השראה, אפשר לעיין במאגר הדוגמאות וההדגמות של GitHub
maps-sdk-for-ios-samples
או ליצור ממנו עותק (fork). - עוד סדנאות תכנות ב-Swift ליצירת אפליקציות ל-iOS באמצעות הפלטפורמה של מפות Google
- כדי לעזור לנו ליצור את התוכן שהכי יעזור לך, נבקש ממך למלא את הסקר הבא:
אילו codelabs נוספים היית רוצה לראות?
לא מוצאים את ה-codelab שהכי מעניין אתכם? כאן אפשר לשלוח בקשה בנושא בעיה חדשה.