הוספת מפה לאפליקציה שלך ל-iOS (Objective-C)

1. לפני שתתחיל

מופשט

בשיעור הקוד הזה תלמדו את כל מה שצריך כדי להתחיל להשתמש באפליקציות של מפות Google כדי לבנות אפליקציות ל-iOS ב-Object-C. נלמד את כל העקרונות הבסיסיים – מרגע ההגדרה ועד הטעינה של ה-SDK של מפות Google ל-iOS, הצגת המפה הראשונה, עבודה עם סמנים ואשכולות סמנים, ציור על המפה וטיפול באינטראקציות של משתמשים.

מה תפתחו

342520482a888519.png

במעבדה הזו תוכלו ליצור אפליקציה ל-iOS שמבצעת את הפעולות הבאות:

  • טוענת את ה-SDK של מפות Google ל-iOS ואת ה-SDK של מפות Google לספריית התשתיות ל-iOS
  • מוצגת מפה שבמרכזה סידני, אוסטרליה
  • הצגת סמנים מותאמים אישית ל-100 נקודות מסביב לסידני
  • מטמיע אשכולות סמנים
  • מאפשר אינטראקציה של משתמש שממורכז מחדש ומציירים עיגול במפה כשלוחצים על סמן

מה תלמדו

  • תחילת העבודה עם מפות Google
  • טעינת SDK של מפות Google ל-iOS ו-SDK של מפות Google ל-iOS Utility Directory
  • המפה נטענת
  • שימוש בסמנים, בסמנים בהתאמה אישית ובאשכולות סמנים
  • עבודה עם מערכת ה-SDK של מפות Google למערכת iOS כדי לספק אינטראקציה עם המשתמש
  • שליטה במפה באופן פרוגרמטי
  • ציור על המפה

דרישות מוקדמות

צריך לעבור על הפריטים הבאים כדי להשלים את ה-Codelab הזה. אם אתם כבר עובדים עם הפלטפורמה של מפות Google, אפשר לדלג קדימה ל-Codelab!

מוצרים נדרשים של הפלטפורמה של מפות Google

בשיעור Lab זה, תשתמשו במוצרים הבאים של מפות Google:

  • SDK של מפות ל-iOS
  • SDK של מפות Google לספריית התשתיות ל-iOS

תחילת העבודה עם הפלטפורמה של מפות Google

אם לא השתמשתם בעבר בפלטפורמה של מפות Google, יש לבצע את המדריך לתחילת העבודה עם מפות Google או לצפות בפלייליסט של הפלטפורמה של מפות Google כדי להשלים את השלבים הבאים:

  1. יוצרים חשבון לחיוב.
  2. יוצרים פרויקט.
  3. הפעלת ממשקי API וערכות SDK של מפות Google (מפורט בקטע הקודם).
  4. יצירת מפתח API.

דרישות אחרות ל-Codelab הזה

כדי להשלים את קוד הקוד הזה, תצטרכו את החשבונות, השירותים והכלים הבאים:

  • חשבון ב-Google Cloud Platform עם חיוב מופעל
  • מפתח API של פלטפורמת מפות Google עם ה-SDK של מפות Google ל-iOS מופעל
  • ידע בסיסי על מטרה-ג
  • Xcode 12.0 עם SDK מגרסה 12.0 ואילך

2. להגדרה

בשלב ההפעלה הבא, יש להפעיל את SDK של מפות Google ל-iOS.

הגדרת מפות Google

אם עדיין אין לכם חשבון Google Cloud Platform ופרויקט שבו מופעל חיוב, כדאי לעיין במדריך תחילת העבודה עם הפלטפורמה של מפות Google ליצירת חשבון לחיוב ופרויקט.

  1. ב-Cloud Console, לוחצים על התפריט הנפתח של הפרויקט ובוחרים את הפרויקט שבו רוצים להשתמש ב-Codelab הזה.

  1. מפעילים את ממשקי ה-API ואת ערכות ה-SDK של מפות Google הנדרשים למעבדת קוד זו ב-Google Cloud Marketplace. כדי לעשות זאת, יש לבצע את השלבים המפורטים בסרטון הזה או בתיעוד הזה.
  2. יוצרים מפתח API בדף פרטי הכניסה ב-Cloud Console. ניתן לבצע את השלבים המפורטים בסרטון הזה או בתיעוד הזה. לכל הבקשות שנשלחות לפלטפורמה של מפות Google נדרש מפתח API.

הגדרת פרויקט Starter Starter

לפני שמתחילים את ה-Codelab הזה, צריך לבצע את הפעולות הבאות כדי להוריד את תבנית הפרויקט למתחילים, וגם את קוד הפתרון המלא:

  1. אפשר להוריד את ה-Repo RepoGuHub למעבדה זו בכתובת https://github.com/googlecodelabs/maps-platform-101-objc.

הפרויקט StarterApp נמצא בספרייה /starter וכולל את מבנה הקובץ הבסיסי הנדרש כדי להשלים את שיעור הקוד. כל מה שצריך לעבוד נמצא בספרייה של /starter/StarterApp.

אם ברצונך לראות את קוד הפתרון המלא, תוכל להשלים את שלבי ההגדרה שלמעלה ולהציג את הפתרון בספרייה /solution/SolutionApp.

3. התקנת SDK של מפות ל-iOS

השלב הראשון בשימוש ב-SDK של מפות Google ל-iOS הוא להתקין את תלויות תלויות. יש שני שלבים בתהליך הזה: התקנת ה-SDK של מפות Google ל-iOS וה-SDK של מפות Google ל-iOS ככלי עזר ממנהל התלות של Cocoapods, והעברת מפתח ה-API ל-SDK.

  1. מוסיפים את ה-SDK של מפות Google ל-iOS ול-Maps SDK עבור ספריית השירותים של iOS אל Podfile.

במעבדה זו נעשה שימוש ב-SDK של מפות Google ל-iOS, שמספק את כל הפונקציות המרכזיות של מפות Google, וגם בספריית השירות של מפות iOS ל-iOS, המספקת מגוון שירותים להעשרה של המפות שלכם, כולל אשכול סמנים.

כדי להתחיל, ב-Xcode (או בעורך הטקסט המועדף עליך) פותחים את Pods > Podfile ומעדכנים את הקובץ כך שיכלול את ה-SDK של מפות Google ל-iOS ולתלויות בספרייה של כלי השירות בקטע use_frameworks!:

pod 'GoogleMaps'
pod 'Google-Maps-iOS-Utils'
  1. מתקינים את ה-SDK של מפות Google ל-iOS ואת ה-SDK של מפות Google ל-iOS Pod SDK.

כדי להתקין את תלויות, יש להריץ את pod install בספרייה /starter משורת הפקודה. Cocoapods יוריד באופן אוטומטי את התלות וייצור StarterApp.xcworkspace. 3. לאחר שהתלויות מותקנות, פותחים את StarterApp.xcworkspace ב-Xcode ולאחר מכן מפעילים את האפליקציה בסימולטור iPhone על ידי הקשה על Command+R. אם כל הפרטים מוגדרים כראוי, הסימולטור יופעל ויציג מסך שחור. אל דאגה, עדיין לא יצרת שום דבר, כך זה צפוי! 4. מייבאים את ה-SDK ב-AppDelegate.h.

עכשיו, בהתאם לתלויות שלכם, הגיע הזמן לספק את מפתח ה-API ל-SDK. השלב הראשון הוא לייבא את ה-SDK של מפות Google ל-iOS כפונקציה על ידי הוספת הערכים הבאים מתחת להצהרת הייבוא #import "AppDelegate.h":

@import GoogleMaps;
  1. מתחת להצהרת הייבוא של iOS SDK, מצהירים על NSString קבוע עם הערך המוגדר למפתח ה-API:
static NSString *const kMapsAPIKey = @"YOUR API KEY";
  1. יש להעביר את מפתח ה-API ל-iOS SDK על ידי התקשרות ל-provideAPIKey ב-GMSServices ב-application: didFinishLaunchingWithOptions:
- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GMSServices provideAPIKey:kMapsAPIKey];
  return YES;
}

עכשיו קובץ ה-AppDelegate.m המעודכן אמור להיראות כך:

#import "AppDelegate.h"
@import GoogleMaps;

static NSString *const kMapsAPIKey = @"YOUR API KEY";

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GMSServices provideAPIKey:kMapsAPIKey];
  return YES;
}
@end

ה-Podfile אמור להיראות כך:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '11.0'

target 'StarterApp' do
  use_frameworks!

pod 'GoogleMaps', '5.1.0.0'
pod 'Google-Maps-iOS-Utils', '3.4.0'

end

עכשיו, בהתאם לתלויות שלכם ומפתח ה-API שלכם מוכן, תוכלו להתחיל להתקשר ל-SDK של מפות Google ל-iOS.

4. הצגת מפה

הגיע הזמן להציג את המפה הראשונה שלך!

החלק הנפוץ ביותר ב-SDK של מפות Google ל-iOS הוא הכיתה GMSMapView, שמספקת שיטות רבות שמאפשרות ליצור מופעים של מפות ולשנות אותם. ככה זה עובד.

  1. פתיחת ViewController.m

כאן תבוצע כל העבודה שנותרה ב-Codelab הזה. אפשר לראות כבר loadView וviewDidLoad אירועים במחזור החיים של בקר התצוגה המפורטת. 2. כדי לייבא את SDK של מפות ל-iOS, צריך להוסיף את הפרטים הבאים בחלק העליון של הקובץ:

@import GoogleMaps;
  1. יש לציין משתנה מופע אחד (ViewController) כדי לאחסן את GMSMapView.

המופע של GMSMapView הוא האובייקט העיקרי שאיתו אתם תעבוד ב-Codelab הזה. אתם תתייחסו אליו ותפעלו לפיו במגוון שיטות במחזור החיים של בקרי התצוגה. כדי להפוך אותו לזמין, יש לעדכן את ההטמעה של ViewController כדי להצהיר על משתנה מכונה כדי לאחסן אותו:

@implementation ViewController {
  GMSMapView *_mapView;
}
  1. ב-loadView, יוצרים מכונה של GMSCameraPosition.

GMSCameraPosition מגדיר את המיקום המרכזי של המפה ואת רמת המרחק מהתצוגה שתוצג. קוד זה קורא לשיטה cameraWithLatitude:longitude:zoom: כדי למרכז את המפה בסידני, אוסטרליה, בקו רוחב של -33.86 וקו האורך של 151.20, עם רמת זום של 12:

GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.86 longitude:151.20 zoom:12];
  1. ב-loadView, יש ליצור מופע של GMSMapView כדי ליצור את המפה מיד.

כדי ליצור מופע מפה חדש יש להתקשר אל mapWithFrame:camera:. שימו לב שהמסגרת מוגדרת ל-CGRectZero, שהוא משתנה גלובלי מספריית CGGeometry ב-iOS . הוא מציין מסגרת של 0 רוחב, 0 גובה, ממוקם במיקום (0,0) בתוך בקר התצוגה. המצלמה מוגדרת למיקום המצלמה שיצרתם.

כדי להציג את המפה בפועל, עליך להגדיר את תצוגת הבסיס של בקר התצוגה ל-_mapview. פעולה זו תגרום להצגת המפה במסך מלא.

_mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
self.view = _mapView;
  1. הגדרת GMSMapViewDelegate לבקר התצוגה.

לאחר הטמעתם, בעל/ת הגישה לתצוגת המפה מאפשר לך לטפל באירועים מאינטראקציות של משתמשים במופע של GMSMapView. יש לך אפשרות לעשות זאת בשלבים הבאים.

תחילה, יש לעדכן את הממשק של ViewController כך שיתאים לפרוטוקול של GMSMapViewDelegate:

@interface ViewController ()<GMSMapViewDelegate>

בשלב הבא, יש להוסיף את הערכים הבאים כדי להגדיר את GMSMapViewDelegate כViewController.

_mapView.delegate = self;

עכשיו טוענים מחדש את האפליקציה בסימולטור ל-iOS (Command+R) והמפה אמורה להופיע.

2e6ebac422323aa6.png

לסיכום, בשלב זה יצרת מופע של GMSMapView להצגת מפה שבמרכזה העיר סידני, אוסטרליה.

עכשיו קובץ ה-ViewController.m אמור להיראות כך:

#import "ViewController.h"
#import "LocationGenerator.h"
@import GoogleMaps;

@interface ViewController ()<GMSMapViewDelegate>
@end

@implementation ViewController {
  GMSMapView *_mapView;
}

- (void)loadView {
  [super loadView];
  GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.86 longitude:151.20 zoom:12];
  _mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
  self.view = _mapView;
  _mapView.delegate = self;
}

5. עיצוב מפה מבוסס ענן (אופציונלי)

אפשר להתאים אישית את סגנון המפה באמצעות סגנון המפה המבוסס על ענן.

יצירת מזהה מפה

אם עדיין לא יצרתם מזהה מפה שמשויכים אליו סגנון מפה, תוכלו להיעזר במדריך מזהי מפות כדי:

  1. יוצרים מזהה מפה.
  2. משייכים מזהה מפה לסגנון מפה.

הוספת מזהה המפה לאפליקציה

כדי להשתמש במזהה המפה שיצרת בשלב הקודם, יש לפתוח את הקובץ ViewController.m ובשיטה loadView ליצור אובייקט GMSMapID ולספק לו את מזהה המפה. בשלב הבא, מגדירים את האובייקט GMSMapID ב-GMSMapView כפרמטר ומשנים את האובייקט.

ViewController.m

- (void)loadView {
    GMSMapID *mapID = [[GMSMapID alloc] initWithIdentifier:@"YOUR_MAP_ID"];
    _mapView = [GMSMapView mapWithFrame:CGRectZero mapID:mapID camera:camera];
    // ...
}

אחרי שמסיימים, מפעילים את האפליקציה כדי לראות את המפה בסגנון שבחרתם.

6. הוספת סמנים למפה

יש הרבה דברים שמפתחים עושים עם ה-SDK של מפות ל-iOS, אבל הוספה של סמנים למפה היא בהחלט הפופולרית ביותר. סמנים מאפשרים לכם להציג נקודות ספציפיות במפה ומשמשים כרכיב נפוץ בממשק המשתמש לטיפול באינטראקציה של משתמשים. אם השתמשתם בעבר במפות Google, סביר להניח שאתם מכירים את סמן ברירת המחדל שנראה כך:

590815267846f166.png

בשלב זה תלמדו איך להשתמש בכיתה GMSMarker כדי להציב סמנים במפה.

לידיעתך, לא ניתן למקם סמנים במפה עד לטעינת המפה מהשלב הקודם באירוע loadView של מחזור החיים של בקר, כך שהשלמתם את השלבים האלה באירוע מחזור החיים של viewDidLoad, הנקראת לאחר טעינת התצוגה (והמפה).

  1. הגדרה של אובייקט CLLocationCoordinate2D.

CLLocationCoordinate2D הוא מבנה הזמין על ידי ספריית CoreLocation ב-iOS, שמגדיר מיקום גיאוגרפי בקו רוחב וקו אורך. כדי להתחיל ליצור את הסמן הראשון, יש להגדיר אובייקט CLLocationCoordinate2D ולהגדיר את קווי הרוחב והאורך במרכז המפה. ניתן לגשת לקואורדינטות של מרכז המפה מתצוגת המפה, באמצעות המאפיינים camera.target.latitude ו-camera.target.longitude.

CLLocationCoordinate2D mapCenter = CLLocationCoordinate2DMake(_mapView.camera.target.latitude, _mapView.camera.target.longitude);
  1. יצירת מכונה של GMSMarker.

ה-SDK של מפות Google ל-iOS מספק את המחלקה GMSMarker. כל מופע של GMSMarker מייצג סמן ספציפי במפה, שנוצר על ידי קריאה ל-markerWithPosition: והעברתו לאובייקט CLLocationCoordinate2D כדי לומר ל-SDK איפה להציב את הסמן במפה.

GMSMarker *marker = [GMSMarker markerWithPosition:mapCenter];
  1. הגדרה של סמל סמן בהתאמה אישית.

סמן הסיכה האדום המוגדר כברירת מחדל עבור מפות Google הוא נהדר, אבל זו גם ההתאמה האישית של המפה שלך! למזלנו, קל מאוד להשתמש בסמן מותאם אישית באמצעות ה-SDK של מפות Google ל-iOS. תוכלו לראות שפרויקט StarterApp כולל תמונה בשם 'custom_pin.png&#39', כדי שתוכלו להשתמש בה בכל תמונה שתרצו.

כדי להגדיר את הסמן המותאם אישית, צריך להגדיר את מאפיין icon של הסמן למופע של UIImage.

marker.icon = [UIImage imageNamed:@"custom_pin.png"];
  1. מעבד את הסמן במפה.

הסמן שלך נוצר, אבל תראה שהוא לא מופיע במפה. לשם כך, יש להגדיר את המאפיין map במופע של GMSMarker למופע של GMSMapView.

marker.map = _mapView;

עכשיו טוענים מחדש את האפליקציה ומעריכים את המפה הראשונה באמצעות סמן.

a4ea8724f8c5ba20.png

לסיכום, בקטע הזה יצרת מופע של הכיתה של GMSMarker והחלת אותו על תצוגת המפה כדי להציג סמן במפה. אירוע מחזור החיים המעודכן ב-viewDOLoad ב-ViewController.m אמור להיראות כך:

- (void)viewDidLoad {
  [super viewDidLoad];

  CLLocationCoordinate2D mapCenter = CLLocationCoordinate2DMake(_mapView.camera.target.latitude, _mapView.camera.target.longitude);
  GMSMarker *marker = [GMSMarker markerWithPosition:mapCenter];
  marker.icon = [UIImage imageNamed:@"custom_pin.png"];
  marker.map = _mapView;
}

7. הפעלה של אשכול סמן

כשאתם משתמשים בסמנים רבים או בסמנים שקרובים זה לזה, אתם עשויים להיתקל בבעיה שבה הסמנים חופפים או שהם מוצגים בצורה עמוסה מדי, מה שגורם לחוויית משתמש גרועה. לדוגמה, אם שני סמנים קרובים מאוד, עלולים להיווצר מצב כזה:

6e39736160c6bce4.png

כאן אשכול הסימונים. אשכול סמנים הוא תכונה נוספת שמיושמת בדרך כלל, ומקבצת סמנים בקרבת מקום לסמל יחיד שמשתנה בהתאם לרמת הזום, כמו:

4abb38cd97cab3f1.png

האלגוריתם לאשכול סמנים מחלק את האזור הגלוי במפה למפה, ולאחר מכן מקבצים סמלים שנמצאים באותו תא. למרבה המזל, אין צורך לדאוג לכך, כי צוות Google Maps Platform יצר ספרייה שימושית בקוד פתוח שנקראת SDK של מפות Google עבור כלי עזר ל-iOS. ספרייה זו, בין היתר, מטפלת באשכולות סמנים באופן אוטומטי. אפשר לקרוא מידע נוסף על אשכול סמנים בתיעוד של הפלטפורמה של מפות Google או לקרוא את המקור של ספריית השירותים של iOS ב-GitHub.

  1. אפשר להוסיף למפה הרבה יותר סמנים.

כדי לראות אשכול של סמנים בפעולה, אתם צריכים לכלול הרבה סמנים במפה. כדי להקל על התהליך, מסופק לכם מחולל סמן נוח בפרויקט למתחילים ב-LocationGenerator.m.

כדי להוסיף למפה סמנים רבים ככל האפשר, צריך פשוט לקרוא generateMarkersNear:count:במחזור החיים של viewDidLoad בבקר התצוגה מתחת לקוד מהשלב הקודם. השיטה יוצרת את מספר הסמנים שצוינו ב-count במיקומים אקראיים מסביב לקואורדינטות שצוינו באובייקט CLLocationCoordinate2D. במקרה כזה, אפשר להעביר אותו למשתנה mapCenter שיצרת קודם. הסימונים מוחזרים ב-NSArray.

NSArray<GMSMarker *> *markerArray = [LocationGenerator generateMarkersNear:mapCenter count:100];
  1. מייבאים את ה-SDK של מפות Google לספריית התשתיות של iOS.

כדי להוסיף את ספריית השירותים של iOS ל-iOS כפרויקט בפרויקט, מוסיפים את הפריטים הבאים לרשימת התלות בחלק העליון של ViewController.m:

@import GoogleMapsUtils;
  1. הגדרת אשכול הסמן.

כדי להשתמש באשכולת הסמן, עליך לספק שלושה דברים כדי להגדיר את אופן הפעולה שלהם: אלגוריתם אשכול, מחולל סמלים ומעבד. האלגוריתם קובע את אופן קיבוץ הסימונים, למשל המרחק בין הסמנים להכללה באותו אשכול. מחולל הסמלים מספק את סמלי האשכול לשימוש ברמות זום שונות. כלי הרינדור מטפל ברינדור בפועל של סמלי האשכול במפה.

תוכלו לכתוב את כל השלבים האלה אם תרצו, אבל ספריית כלי הניהול של מפות Google ל-iOS מספקת הטמעות ברירת מחדל כדי להקל על התהליך. פשוט מוסיפים את הפרטים הבאים:

id<GMUClusterAlgorithm> algorithm = [[GMUNonHierarchicalDistanceBasedAlgorithm alloc] init];

id<GMUClusterIconGenerator> clusterIconGenerator = [[GMUDefaultClusterIconGenerator alloc] init];

id<GMUClusterRenderer> renderer = [[GMUDefaultClusterRenderer alloc] initWithMapView:_mapView clusterIconGenerator:clusterIconGenerator];
  1. יצירת מכונה של GMUClusterManager.

GMUClusterManager היא השיעור המטמיע אשכולות סמנים, באמצעות האלגוריתם, מחולל הסמלים והרינדור שציינתם. כדי ליצור את כלי הרינדור ולהפוך אותו לזמין לתצוגת המפה, תחילה יש להוסיף משתנה מופע להטמעה של ViewController כדי לאחסן את המופע של מנהל האשכול.

@implementation ViewController {
  GMSMapView *_mapView;
  GMUClusterManager *_clusterManager;
}

לאחר מכן, יוצרים את המופע של GMUClusterManager באירוע מחזור החיים של viewDidLoad:

_clusterManager = [[GMUClusterManager alloc] initWithMap:_mapView algorithm:algorithm renderer:renderer];
  1. מוסיפים את הסמנים ומפעילים את אשכול הסמן.

עכשיו, לאחר שהגדרת את מקבץ האשכולות שלך, כל שעליך לעשות הוא להעביר את מערך הסימונים של האשכול לאשכולות על ידי קריאה ל-addItems: ואז להריץ את האשכול באמצעות קריאה ל-cluster.

[_clusterManager addItems:markerArray];
[_clusterManager cluster];

טוענים מחדש את האפליקציה, ועכשיו צריך לראות המון סימונים מקובצים. כדי להתקדם ולשחק עם רמות זום שונות, אפשר לעשות תנועת צביטה ולשנות את מרחק התצוגה במפה, כדי לראות את אשכולות הסמן כשמגדילים או מקטינים.

c49383b07752bfc4.png

לסיכום, בשלב זה הגדרתם מופע של אשכול הסימונים מה-SDK של מפות Google ל-iOS Utility Directory, ולאחר מכן השתמשתם בו כדי לקבץ 100 סמנים במפה. אירוע מחזור החיים של viewDidLoad בViewController.m אמור להיראות כך:

- (void)viewDidLoad {
  [super viewDidLoad];

  CLLocationCoordinate2D mapCenter = CLLocationCoordinate2DMake(_mapView.camera.target.latitude,
                                                                _mapView.camera.target.longitude);
  GMSMarker *marker = [GMSMarker markerWithPosition:mapCenter];
  marker.icon = [UIImage imageNamed:@"custom_pin.png"];
  marker.map = _mapView;
  NSArray<GMSMarker *> *markerArray = [LocationGenerator generateMarkersNear:mapCenter count:100];

  id<GMUClusterAlgorithm> algorithm = [[GMUNonHierarchicalDistanceBasedAlgorithm alloc] init];
  id<GMUClusterIconGenerator> clusterIconGenerator = [[GMUDefaultClusterIconGenerator alloc] init];
  id<GMUClusterRenderer> renderer = [[GMUDefaultClusterRenderer alloc] initWithMapView:_mapView clusterIconGenerator:clusterIconGenerator];
  _clusterManager = [[GMUClusterManager alloc] initWithMap:_mapView algorithm:algorithm renderer:renderer];

  [_clusterManager addItems:markerArray];
  [_clusterManager cluster];
}

8. אינטראקציה של משתמש

עכשיו יש לך מפה נראית טובה שמציגה סמנים ומשתמשת באשכולות סמנים. בשלב זה, עליך להוסיף עוד טיפול על אינטראקציות המשתמשים באמצעות GMSMapViewDelegate, שהגדרת קודם לבקר המידע על התצוגה, כדי לשפר את חוויית המשתמש במפה.

ה-SDK של מפות ל-iOS מספק מערכת אירועים מקיפה שמיושמת באמצעות הענקת גישה לתצוגת מפה, הכוללת רכיבי handler של אירועים שמאפשרים להפעיל קוד כשמתרחשות אינטראקציות שונות של משתמשים. לדוגמה, ההאצלה של תצוגת המפה כוללת שיטות שמאפשרות לך להפעיל הפעלת קוד עבור אינטראקציות כמו המשתמש לוחץ על המפה ועל הסמנים, הזזה של תצוגת המפה, התקרבות לתצוגה ועוד.

בשלב זה, עליך להגדיר באופן פרוגרמטי את הזזה במפה כך שתמרכז את הסמן על כל סמן שעליו מקיש המשתמש.

  1. הטמעה של מכשיר ההאזנה בהקשה.

מתבצעת קריאה ל-mapView:didTapMarker בכל פעם שהמשתמש מקיש על אחד מהסמנים שיצרת קודם, וגם בכל פעם שמשתמש מקיש על אשכול סמנים (אשכולות פנימיים מיושמים כמופע של GMSMarker).

כדי להטמיע את הפונקציה event listener, יש להוסיף את החלק התחתון בחלק התחתון של ה-ViewController.m לפני ההצהרה end.

אפשר לראות שהשיטה מחזירה NO. פעולה זו מורה ל-iOS SDK להמשיך לבצע את פונקציונליות ברירת המחדל של GMSMarker, כמו הצגת חלון מידע, אם מוגדר, לאחר ביצוע קוד ה-handler של האירוע.

- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {

  return NO;
}
  1. יש לטפל באירוע ההקשה ולהגדיר אנימציה של המצלמה כדי למרכז את המפה כאשר מקישים על סמן או על אשכול סמנים.

כשמתקשרים, mapView:didTapMarker מעביר את המופע של GMSMarker שנלחץ, ומאפשר לך לטפל בו בקוד. ניתן להשתמש במופע הזה כדי למרכז את המפה על ידי קריאה ל-animateToLocation: בתצוגת המפה מתוך ה-handler של האירוע ולהעברת המיקום של מופע הסמן, הזמין בנכס position.

[_mapView animateToLocation:marker.position];
  1. הגדלת התצוגה של אשכול הסמן בעת הקשה.

דפוס טיפוסי של חוויית משתמש הוא הגדלת האשכולות של הסמן בעת ההקשה. כך המשתמשים יוכלו להציג את הסימונים המקובצים באשכולות, כי האשכול יורחב ברמות נמוכות יותר.

כפי שצוין קודם, סמל אשכול הסמן הוא למעשה הטמעה של GMSMarker עם סמל מותאם אישית. אז איך אפשר לדעת אם בוצעה הקשה על סמן או על אשכול סימנים? כאשר מנהל האשכולות של הסמן יוצר סמל אשכול חדש, הוא מטמיע את המופע של GMSMarker כדי להתאים לפרוטוקול בשם GMUCluster. תוכל להשתמש בתנאי כדי לבדוק אם הסמן המועבר אל ה-handler של האירועים תואם לפרוטוקול הזה.

אחרי שידוע שמקישים על אשכול באופן פרוגרמטי, אפשר להתקשר ל-animateToZoom: במופע של תצוגת המפה ולהגדיר את מרחק התצוגה לרמת הזום הנוכחית. רמת המרחק הנוכחית זמינה במופע של תצוגת המפה בנכס camera.zoom.

כמו כן, חשוב לשים לב איך הקוד הבא מחזיר את YES. פעולה זו נותנת ל-handler של האירוע שהשלמתם את הטיפול באירוע ולא להפעיל קוד נוסף ב-handler. אחת מהסיבות לכך היא למנוע מאובייקט GMSMarker לבצע את שאר התנהגות ברירת המחדל שלו, כמו הצגת חלון מידע שלא יהיה הגיוני במקרה של הקשה על סמל של אשכול.

if ([marker.userData conformsToProtocol:@protocol(GMUCluster)]) {
    [_mapView animateToZoom:_mapView.camera.zoom +1];
    return YES;
}

עכשיו טוענים מחדש את האפליקציה ומקישים על כמה סמנים ואשכולות סמנים. לאחר ההקשה, המפה תופיע מחדש באלמנט שעליו הקשת. כאשר מקישים על אשכול סמן, המפה תגדל גם ברמה אחת, ואשכול הסמן יתרחב כדי להציג את הסימונים המקובצים במקבצים.

לסיכום, בשלב זה הטמעתם את הכלי להאזנה בהקשה

שיטת mapView:didTapMarker צריכה להיראות כך:

- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {
  [_mapView animateToLocation:marker.position];

  if ([marker.userData conformsToProtocol:@protocol(GMUCluster)]) {
    [_mapView animateToZoom:_mapView.camera.zoom +1];
    return YES;
  }

  return NO;
}

9. ציור על המפה

עד כה, יצרתם מפה של סידני שמציגה סמנים ב-100 נקודות אקראיות ומטפלת באינטראקציות של משתמשים. בשלב האחרון של שיעור הקוד הזה, תשתמשו בתכונות הציור של ה-SDK של מפות Google ל-iOS כדי להוסיף עוד תכונה שימושית לחוויית המפה.

נניח שהמפה הזו תשמש את המשתמשים שרוצים לחקור את העיר סידני. תכונה שימושית היא תצוגה חזותית של רדיוס מסביב לסמן בזמן לחיצה עליו. כך המשתמש יוכל להבין בקלות אילו יעדים אחרים נמצאים במרחק הליכה קל מהסמן שעליו הוא לוחץ.

ה-SDK של iOS כולל קבוצה של פונקציות לציור צורות במפה, כמו ריבועים, פוליגונים, קווים ומעגלים. בשלב הבא, יוצרים עיגול כדי להציג רדיוס של 800 מטר מסביב לסמן, כשלוחצים עליו.

  1. יש להוסיף משתנה מופע _circ אל ה-ViewController.

משתנה מופע זה ישמש לשמירת העיגול האחרון שציורו, כדי שניתן יהיה להשמיד אותו לפני ציור אחר. אחרי מכן, זה לא יהיה מועיל למשתמש. זה ייראה די גרוע אם כל סמן שעליו הקשת יכסה עיגול מסביב!

לשם כך, יש לעדכן את ההטמעה של ViewController באופן הבא:

@implementation ViewController {
  GMSMapView *_mapView;
  GMUClusterManager *_clusterManager;
  GMSCircle *_circ;
}
  1. משרטטים את העיגול כשמקישים על סמן.

בחלק התחתון של השיטה mapView:didTapMarker, מוסיפים את הקוד הבא כדי ליצור מופע של כיתה GMSCircle של iOS SDK ומשרטטים מעגל רדיוס חדש של 800 מטר על ידי קריאה ל-circleWithPosition:radius: והעברתו למיקום של סמן הקשת, בדיוק כפי שעשיתם למעלה כשהמרתם את המפה.

_circ = [GMSCircle circleWithPosition:marker.position radius:800];
  1. מעצבים את המעגל.

כברירת מחדל, GMSCircle משרטטת מעגל עם קו חוצה מלא ומילוי שקוף. זה יעבוד כדי להציג את הרדיוס, אבל הוא לא נראה טוב במיוחד וקצת קשה לראות אותו. לאחר מכן, אפשר לשנות את הסגנון של המעגל כדי לשפר את העיצוב על ידי הקצאת UIColor למאפיין fillColor של העיגול. הקוד הבא יוסיף מילוי אפור בשקיפות של 50%:

_circ.fillColor = [UIColor colorWithRed: 0.67 green: 0.67 blue: 0.67 alpha: 0.5];
  1. עיבוד העיגול במפה.

בדיוק כמו שיצרתם סמנים מוקדם יותר, תבחינו בכך שיצירת מופע של GMSCircle לא גורמת לכך להופיע במפה. לשם כך, יש להקצות את המופע של תצוגת המפה לנכס map בעיגול.

_circ.map = _mapView;
  1. יש להסיר מעגלים שעובדו בעבר.

כפי שצוין קודם לכן, לא תהיה חוויית משתמש טובה מאוד רק כדי להמשיך להוסיף מעגלים למפה. כדי להסיר את העיגול שנוצר על ידי אירוע הקשה קודם, יש להגדיר את המאפיין map של _circ ל-nil בחלק העליון של mapView:didTapMarker.

_circ.map = nil;

טוענים מחדש את האפליקציה ומקישים על סמן. אתם אמורים לראות עיגול חדש שמצולם בכל פעם שמקישים על סמן, וכל עיגול שעבר עיבוד בעבר הוסר.

342520482a888519.png

לסיכום, בשלב הזה השתמשת בכיתה GMSCircle כדי לעבד עיגול בכל פעם שמקישים על סמן.

שיטת mapView:didTapMarker צריכה להיראות כך:

- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {
  _circ.map = nil;
  [_mapView animateToLocation:marker.position];

  if ([marker.userData conformsToProtocol:@protocol(GMUCluster)]) {
    [_mapView animateToZoom:_mapView.camera.zoom +1];
    return YES;
  }

  _circ = [GMSCircle circleWithPosition:marker.position radius:800];
  _circ.fillColor = [UIColor colorWithRed: 0.67 green: 0.67 blue: 0.67 alpha: 0.5];
  _circ.map = _mapView;
  return NO;
}

10. מזל טוב

בנית בהצלחה את האפליקציה הראשונה שלך ל-iOS באמצעות הפלטפורמה של מפות Google, כולל טעינת ה-SDK של מפות Google ל-iOS, טעינת מפה, עבודה עם סמנים, שליטה וציור במפה והוספת אינטראקציה עם משתמשים.

כדי לראות את הקוד המלא, יש לבדוק את הפרויקט המוגמר בספרייה /solution.

מה עכשיו?

במעבדה זו עברנו רק את מה שאפשר לעשות עם SDK של iOS ל-iOS. בשלב הבא, נסו להוסיף למפה חלק מהתכונות הבאות:

כדי לקבל עוד דרכים לעבוד עם הפלטפורמה של מפות Google באינטרנט, כדאי לעיין בקישורים הבאים: