شروع کار با Consumer SDK برای iOS

می‌توانید از Consumer SDK برای ساخت و اجرای یک برنامه مصرف‌کننده اساسی که با خدمات باطنی Rides و Deliveries Solution بر اساس تقاضا یکپارچه شده است، استفاده کنید. می توانید یک برنامه Trip and Order Progress ایجاد کنید که می تواند یک سفر فعال را نمایش دهد، به به روز رسانی سفر پاسخ دهد و خطاهای سفر را مدیریت کند.

از آنجایی که Consumer SDK یک معماری ماژولار دارد، می‌توانید از بخش‌هایی از API که می‌خواهید برای برنامه خاص خود استفاده کنید استفاده کنید و آن‌ها را با APIهای خود، سرویس‌های Backend ارائه‌شده توسط Fleet Engine و API‌های اضافی پلتفرم Google Maps ادغام کنید. .

کمترین سیستم مورد نیاز

  • دستگاه تلفن همراه باید دارای iOS 14 یا جدیدتر باشد.
  • Xcode نسخه 15 یا بالاتر.
  • پیکربندی پروژه

    مدیر بسته سوئیفت

    Consumer SDK را می توان از طریق Swift Package Manager نصب کرد. برای افزودن SDK، مطمئن شوید که وابستگی های موجود در SDK مصرف کننده را حذف کرده اید.

    برای افزودن SDK به یک پروژه جدید یا موجود، مراحل زیر را دنبال کنید:

    1. project یا workspace Xcode خود را باز کنید، سپس به File > Add Package Dependencies بروید.
    2. https://github.com/googlemaps/ios-consumer-sdk را به عنوان URL وارد کنید، Enter را فشار دهید تا بسته را وارد کنید و روی «افزودن بسته» کلیک کنید.
    3. برای نصب یک version خاص، قسمت Dependency Rule را روی یکی از گزینه های مبتنی بر نسخه تنظیم کنید. برای پروژه های جدید، توصیه می کنیم آخرین نسخه را مشخص کنید و از گزینه "نسخه دقیق" استفاده کنید. پس از تکمیل، روی "افزودن بسته" کلیک کنید.
    4. از پنجره انتخاب محصولات بسته ، تأیید کنید که GoogleRidesharingConsumer به هدف main تعیین‌شده شما اضافه می‌شود. پس از تکمیل، روی "افزودن بسته" کلیک کنید.
    5. برای تأیید نصب خود، به صفحه General هدف خود بروید. در Frameworks، Libraries و Embedded Content باید بسته های نصب شده را ببینید. همچنین می‌توانید برای تأیید بسته و نسخه آن، بخش «وابستگی‌های بسته» در «ناوبر پروژه» را مشاهده کنید.

    برای به روز رسانی package برای یک پروژه موجود، این مراحل را دنبال کنید:

    1. از Xcode، به "File > Packages > Update To Latest Package Versions" بروید.
    2. برای تأیید نصب خود، به بخش Package Dependencies در Project Navigator بروید تا بسته و نسخه آن را تأیید کنید.

    برای حذف وابستگی‌های Consumer SDK موجود با استفاده از CocoaPods ، این مراحل را دنبال کنید:

    1. فضای کاری Xcode خود را ببندید. ترمینال را باز کنید و دستور زیر را اجرا کنید:
      sudo gem install cocoapods-deintegrate cocoapods-clean 
      pod deintegrate 
      pod cache clean --all
    2. اگر از آنها برای چیزی غیر از CocoaPods استفاده نمی کنید، Podfile ، Podfile.resolved و workspace Xcode را حذف کنید.

    برای حذف Consumer SDK موجود که به صورت دستی نصب شده است، این مراحل را دنبال کنید:

    1. از تنظیمات پیکربندی پروژه Xcode خود، Frameworks، Libraries و Embedded Content را پیدا کنید. از علامت منفی (-) برای حذف چارچوب زیر استفاده کنید:

      • GoogleRidesharingConsumer.xcframework
    2. از دایرکتوری سطح بالای پروژه Xcode خود، بسته GoogleRidesharingConsumer را حذف کنید.

    CocoaPods

    برای پیکربندی Consumer SDK با استفاده از CocoaPods، به موارد زیر نیاز دارید:

    • ابزار CocoaPods: برای نصب این ابزار، Terminal را باز کرده و دستور زیر را اجرا کنید.

      sudo gem install cocoapods
      

    برای جزئیات بیشتر به راهنمای شروع CocoaPods مراجعه کنید.

    1. یک Podfile برای Consumer SDK ایجاد کنید و از آن برای نصب API و وابستگی های آن استفاده کنید. ابتدا فایلی به نام Podfile در دایرکتوری پروژه خود ایجاد کنید. این فایل وابستگی های پروژه شما را تعریف می کند. سپس Podfile را ویرایش کنید و وابستگی های خود را اضافه کنید. در اینجا یک مثال است که شامل وابستگی ها می شود:

        source "https://github.com/CocoaPods/Specs.git"
      
        target 'YOUR_APPLICATION_TARGET_NAME_HERE' do
          pod 'GoogleRidesharingConsumer'
        end
      
    2. پادفایل را ذخیره کنید. یک ترمینال را باز کنید و به دایرکتوری حاوی Podfile بروید:

      cd <path-to-project>
      
    3. دستور نصب pod را اجرا کنید. این API های مشخص شده در Podfile را به همراه وابستگی هایی که ممکن است داشته باشند نصب می کند.

      pod install
      
    4. Xcode را ببندید و سپس فایل .xcworkspace پروژه خود را باز کنید (دوبار کلیک کنید) تا Xcode راه اندازی شود. برای باز کردن پروژه بعداً، از فایل xcworkspace. استفاده کنید.

    نصب دستی

    XCFramework یک بسته باینری است که برای نصب Consumer SDK از آن استفاده می کنید. شما می توانید از این بسته در چندین پلتفرم از جمله ماشین هایی که از چیپست M1 استفاده می کنند استفاده کنید. این راهنما نشان می دهد که چگونه XCFramework حاوی Consumer SDK را به صورت دستی به پروژه خود اضافه کنید و تنظیمات ساخت خود را در Xcode پیکربندی کنید.

    باینری و منابع SDK را دانلود کنید:

    1. برای دسترسی به XCFramework و منابع، فایل های فشرده شده را باز کنید.

    2. Xcode را راه اندازی کنید و یک پروژه موجود را باز کنید یا یک پروژه جدید ایجاد کنید. اگر در iOS تازه کار هستید، یک پروژه جدید ایجاد کنید و قالب iOS App را انتخاب کنید.

    3. در صورتی که قبلاً وجود نداشته باشد، یک گروه Frameworks در زیر گروه پروژه خود ایجاد کنید.

    4. برای نصب Consumer SDK، فایل GoogleRidesharingConsumer.xcframework را به داخل پروژه خود در بخش Frameworks, Libraries, and Embedded Content بکشید. هنگامی که از شما خواسته شد، در صورت نیاز، کپی موارد را انتخاب کنید.

    5. GoogleRidesharingConsumer.bundle دانلود شده را به دایرکتوری سطح بالای پروژه Xcode خود بکشید. هنگامی که از شما خواسته شد، Copy items if needed را انتخاب کنید.

    6. پروژه خود را از Project Navigator انتخاب کنید و هدف برنامه خود را انتخاب کنید.

    7. تب Build Phases را باز کنید و در پیوند باینری با کتابخانه‌ها، چارچوب‌ها و کتابخانه‌های زیر را در صورتی که قبلاً موجود نیستند اضافه کنید:

      • Accelerate.framework
      • CoreData.framework
      • CoreGraphics.framework
      • CoreImage.framework
      • CoreLocation.framework
      • CoreTelephony.framework
      • CoreText.framework
      • GLKit.framework
      • ImageIO.framework
      • libc++.tbd
      • libz.tbd
      • Metal.framework
      • OpenGLES.framework
      • QuartzCore.framework
      • SystemConfiguration.framework
      • UIKit.framework
    8. پروژه خود را به جای یک هدف خاص انتخاب کنید و تب Build Settings را باز کنید. در بخش Other Linker Flags ، -ObjC هم برای رفع اشکال و هم برای انتشار اضافه کنید. اگر این تنظیمات قابل مشاهده نیستند، فیلتر موجود در نوار تنظیمات ساخت را از Basic به All تغییر دهید.

    فایل Manifest Privacy Apple را اضافه کنید

    1. بسته Manifest Privacy Manifest را برای Consumer SDK برای iOS دانلود کنید: GoogleRidesharingConsumerPrivacy .
    2. برای دسترسی به GoogleRidesharingConsumerPrivacy.bundle فایل را استخراج کنید.
    3. GoogleRidesharingConsumerPrivacy.bundle را با استفاده از یکی از این روش‌ها به ناوبری پروژه Xcode اضافه کنید. مطمئن شوید که کادر «افزودن به اهداف» برای هدف برنامه شما علامت زده شده است. پس از اضافه شدن، فایل PrivacyInfo در Project Navigator نمایش داده می شود و می توانید مقادیر را بررسی کنید.
    4. عکس صفحه اطلاعات حریم خصوصی Xcode
    5. با ایجاد یک بایگانی از برنامه خود و ایجاد یک گزارش حریم خصوصی از بایگانی، تأیید کنید که مانیفست حریم خصوصی اضافه شده است.

    یکپارچه سازی برنامه

    کد احراز هویت را ارائه دهید

    وقتی برنامه Consumer شما از Fleet Engine به‌روزرسانی سفر درخواست می‌کند، درخواست‌ها باید شامل نشانه‌های دسترسی معتبر باشند. برای تأیید و تأیید اعتبار این درخواست‌ها، Consumer SDK شی شما را مطابق با پروتکل GMTCAuthorization فراخوانی می‌کند. شی مسئول ارائه نشانه دسترسی مورد نیاز است.

    به عنوان توسعه‌دهنده برنامه، نحوه تولید توکن‌ها را انتخاب می‌کنید. پیاده سازی شما باید توانایی انجام موارد زیر را داشته باشد:

    • یک نشانه دسترسی، احتمالاً در قالب JSON، از یک سرور HTTPS واکشی کنید.
    • رمز را تجزیه و کش کنید.
    • زمانی که توکن منقضی شد، آن را رفرش کنید.

    برای جزئیات بیشتر توکن‌های مورد انتظار توسط سرور Fleet Engine، به ایجاد یک نشانه وب JSON (JWT) برای مجوز مراجعه کنید.

    شناسه ارائه دهنده همان شناسه پروژه Google Cloud است. برای اطلاعات بیشتر، شروع به کار با Fleet Engine را ببینید.

    مثال زیر یک ارائه دهنده نشانه دسترسی را پیاده سازی می کند:

    سریع

    /*
    
        *   SampleAccessTokenProvider.swift
     */
    import GoogleRidesharingConsumer
    
    private let providerURL = "INSERT_YOUR_TOKEN_PROVIDER_URL"
    
    class SampleAccessTokenProvider: NSObject, GMTCAuthorization {
      private struct AuthToken {
        // The cached trip token.
        let token: String
        // Keep track of when the token expires for caching.
        let expiration: TimeInterval
        // Keep track of the trip ID the cached token is for.
        let tripID: String
      }
    
      enum AccessTokenError: Error {
        case missingAuthorizationContext
        case missingData
      }
    
      private var authToken: AuthToken?
    
      func fetchToken(
        with authorizationContext: GMTCAuthorizationContext?,
        completion: @escaping GMTCAuthTokenFetchCompletionHandler
      ) {
        // Get the trip ID from the authorizationContext. This is set by the Consumer SDK.
        guard let authorizationContext = authorizationContext else {
          completion(nil, AccessTokenError.missingAuthorizationContext)
          return
        }
        let tripID = authorizationContext.tripID
    
        // If appropriate, use the cached token.
        if let authToken = authToken,
          authToken.expiration > Date.now.timeIntervalSince1970 && authToken.tripID == tripID
        {
          completion(authToken.token, nil)
          return
        }
    
        // Otherwise, try to fetch a new token from your server.
        let request = URLRequest(url: URL(string: providerURL))
        let task = URLSession.shared.dataTask(with: request) { [weak self] data, _, error in
          guard let strongSelf = self else { return }
          guard error == nil else {
            completion(nil, error)
            return
          }
    
          // Replace the following key values with the appropriate keys based on your
          // server's expected response.
          let tripTokenKey = "TRIP_TOKEN_KEY"
          let tokenExpirationKey = "TOKEN_EXPIRATION"
          guard let data = data,
            let fetchData = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
            let token = fetchData[tripTokenKey] as? String,
            let expiration = fetchData[tokenExpirationKey] as? Double
          else {
            completion(nil, AccessTokenError.missingData)
            return
          }
    
          strongSelf.authToken = AuthToken(token: token, expiration: expiration, tripID: tripID)
          completion(token, nil)
        }
        task.resume()
      }
    }
    

    هدف-C

    /*
    
        *   SampleAccessTokenProvider.h
     */
    #import <Foundation/Foundation.h>
    #import <GoogleRidesharingConsumer/GoogleRidesharingConsumer.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface SampleAccessTokenProvider : NSObject <GMTCAuthorization>
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    /*
    
        *   SampleAccessTokenProvider.m
     */
    #import "SampleAccessTokenProvider.h"
    #import "GoogleRidesharingConsumer/GoogleRidesharingConsumer.h"
    
    static NSString *const PROVIDER_URL = @"INSERT_YOUR_TOKEN_PROVIDER_URL";
    
    // SampleAccessTokenProvider.m
    @implementation SampleAccessTokenProvider {
      // The cached token with claims to the current trip.
      NSString *_cachedTripToken;
      // Keep track of the Trip ID the cached token is for.
      NSString *_lastKnownTripID;
      // Keep track of when tokens expire for caching.
      NSTimeInterval _tokenExpiration;
    }
    
    -   (void)fetchTokenWithContext:(nullable GMTCAuthorizationContext *)authorizationContext
                       completion:(nonnull GMTCAuthTokenFetchCompletionHandler)completion {
      // Get the trip ID from the authorizationContext. This is set by the Consumer SDK.
      NSString *tripID = authorizationContext.tripID;
    
      // Clear cached trip token if trip ID has changed.
      if (![_lastKnownTripID isEqual:tripID]) {
        _tokenExpiration = 0.0;
        _cachedTripToken = nil;
      }
      _lastKnownTripID = tripID;
    
      // Clear cached tripToken if it has expired.
      if ([[NSDate date] timeIntervalSince1970] > _tokenExpiration) {
        _cachedTripToken = nil;
      }
    
      // If appropriate, use the cached token.
      if (_cachedTripToken) {
        completion(_cachedTripToken, nil);
        return;
      }
      // Otherwise, try to fetch a new token from your server.
      NSURL *requestURL = [NSURL URLWithString:PROVIDER_URL];
      NSMutableURLRequest *request =
          [[NSMutableURLRequest alloc] initWithURL:requestURL];
      request.HTTPMethod = @"GET";
    
      // Replace the following key values with the appropriate keys based on your
      // server's expected response.
      NSString *tripTokenKey = @"TRIP_TOKEN_KEY";
      NSString *tokenExpirationKey = @"TOKEN_EXPIRATION";
    
      __weak typeof(self) weakSelf = self;
      void (^handler)(NSData *_Nullable data, NSURLResponse *_Nullable response,
                      NSError *_Nullable error) =
          ^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError *_Nullable error) {
            typeof(self) strongSelf = weakSelf;
            if (error) {
              completion(nil, error);
              return;
            }
    
            NSError *JSONError;
            NSMutableDictionary *JSONResponse =
                [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&JSONError];
    
            if (JSONError) {
              completion(nil, JSONError);
              return;
            } else {
              // Sample code only. No validation logic.
              id expirationData = JSONResponse[tokenExpirationKey];
              if ([expirationData isKindOfClass:[NSNumber class]]) {
                NSTimeInterval expirationTime = ((NSNumber *)expirationData).doubleValue;
                strongSelf->_tokenExpiration = [[NSDate date] timeIntervalSince1970] + expirationTime;
              }
              strongSelf->_cachedTripToken = JSONResponse[tripTokenKey];
              completion(JSONResponse[tripTokenKey], nil);
            }
          };
      NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
      NSURLSession *mainQueueURLSession =
          [NSURLSession sessionWithConfiguration:config delegate:nil
                                   delegateQueue:[NSOperationQueue mainQueue]];
      NSURLSessionDataTask *task = [mainQueueURLSession dataTaskWithRequest:request completionHandler:handler];
      [task resume];
    }
    
    @end
    

    مقداردهی اولیه برنامه

    سریع

    /*
    
        *   AppDelegate.swift
     */
    import GoogleRidesharingConsumer
    import GoogleMaps
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
      func application(_ application: UIApplication,
          didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Register your API key for GMSServices.
        GMSServices.provideAPIKey(yourMapsAPIKey)
    
        // Set the instance of the SampleAccessTokenProvider.
        GMTCServices.setAccessTokenProvider(SampleAccessTokenProvider(), providerID: yourProviderID)
    
        // Other initialization code ...
        return true
      }
    }
    

    هدف-C

    /*
    
        *   AppDelegate.m
     */
    #import <GoogleMaps/GoogleMaps.h>
    #import <GoogleRidesharingConsumer/GoogleRidesharingConsumer.h>
    
    @implementation AppDelegate
    
    -   (BOOL)application:(UIApplication *)application
        didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
      //Register your API key for GMSServices.
      [GMSServices provideAPIKey:yourMapsAPIKey];
    
      //Set the instance of the AccessTokenFactory.
      [GMTCServices setAccessTokenProvider:[[SampleAccessTokenProvider alloc] init]
                                providerID:yourProviderID];
    
      // Other initialization code ...
      return YES;
    }
    
    @end
    

    ادغام نمای نقشه

    نمای نقشه را اولیه کنید

    مثال زیر نحوه تنظیم اولیه GMTCMapView را نشان می دهد.

    سریع

    /*
    
        *   MapViewController.swift
     */
    class ViewController: UIViewController, GMTCMapViewDelegate {
      private var rideSharingMap: GMTCMapView?
    
      override func viewDidLoad() {
        super.viewDidLoad()
    
        self.rideSharingMap = GMTCMapView(frame: UIScreen.main.bounds)
        self.rideSharingMap.delegate = self
        self.rideSharingMap?.settings.myLocationButton = true
        self.view.addSubview(self.rideSharingMap!)
        ...
      }
    

    هدف-C

    /*
    
        *   MapViewController.h
     */
    @interface MapViewController : UIViewController<GMTCMapViewDelegate>
    ...
    @end
    
    /*
    
        *   MapViewController.m
     */
    @implementation MapViewController
    
    -   (void)viewDidLoad {
      [super viewDidLoad];
      ...
      self.mapView = [[GMTCMapView alloc] initWithFrame:CGRectZero];
      self.mapView.settings.myLocationButton = YES;
      self.mapView.delegate = self;
      ...
    }
    
    ...
    
    @end
    

    رویدادهای نمایش نقشه را مدیریت کنید

    مثال زیر نشان می دهد که چگونه می توان یک نماینده را برای مدیریت رویدادهای وضعیت مشتری پیاده سازی کرد.

    سریع

    func mapViewDidInitialize(_ mapview: GMTCMapView) {
      // Handle the update to the state of the map view to browsing.
    }
    
    func mapView(_ mapView: GMSMapView, didTapConsumerMarker mapMarker: GMSMarker, markerType: GMTCMapViewMarkerType) -> Bool {
      // Handle the mapView marker was tapped.
    }
    

    هدف-C

    /*
    
        *   MapViewController.m
     */
    #pragma mark - GMTCMapViewDelegate implementation
    
    // Handle state update of map view.
    
    -   (void)mapViewDidInitializeCustomerState:(GMTCMapView *)mapview {
      // Handle the update to the state of the map view to browsing.
    }
    
    -   (void)mapView:(GMSMapView *)mapView
        didTapConsumerMarker:(nonnull GMSMarker *)mapMarker
                  markerType:(GMTCMapViewMarkerType)markerType {
      // Handle the mapView marker was tapped.
    }
    

    اشتراک گذاری سفر

    زمانی که نمای بارگیری شد، سفر جدیدی را شروع کنید

    مثال زیر نحوه شروع اشتراک گذاری سفر را بلافاصله پس از بارگیری نمای نشان می دهد. می‌توانید تمام ورودی‌های کاربر مانند مکان‌های تحویل و تحویل را از یک ViewController جمع‌آوری کنید، و سپس یک ViewController جدید ایجاد کنید تا اشتراک‌گذاری سفر را مستقیماً شروع کنید.

    سریع

    /*
    
        *   MapViewController.swift
     */
    override func viewDidLoad() {
      super.viewDidLoad()
      ...
      self.mapView = GMTCMapView(frame: UIScreen.main.bounds)
      self.mapView.delegate = self
      self.view.addSubview(self.mapView)
    }
    
    func mapViewDidInitializeCustomerState(_: GMTCMapView) {
      self.mapView.pickupLocation = self.selectedPickupLocation
      self.mapView.dropoffLocation = self.selectedDropoffLocation
    
      self.startConsumerMatchWithLocations(
        pickupLocation: self.mapView.pickupLocation!,
        dropoffLocation: self.mapView.dropoffLocation!
      ) { [weak self] (tripName, error) in
        guard let strongSelf = self else { return }
        if error != nil {
          // print error message.
          return
        }
        let tripService = GMTCServices.shared().tripService
        // Create a tripModel instance for listening the update of the trip
        // specified by this trip name.
        let tripModel = tripService.tripModel(forTripName: tripName)
        // Create a journeySharingSession instance based on the tripModel
        let journeySharingSession = GMTCJourneySharingSession(tripModel: tripModel)
        // Add the journeySharingSession instance on the mapView for UI updating.
        strongSelf.mapView.show(journeySharingSession)
        // Register for the trip update events.
        tripModel.register(strongSelf)
    
        strongSelf.currentTripModel = tripModel
        strongSelf.currentJourneySharingSession = journeySharingSession
        strongSelf.hideLoadingView()
      }
    
      self.showLoadingView()
    }
    

    هدف-C

    /*
    
        *   MapViewController.m
     */
    -   (void)viewDidLoad {
      [super viewDidLoad];
      ...
      self.mapView = [[GMTCMapView alloc] initWithFrame:CGRectZero];
      self.mapView.delegate = self;
      [self.view addSubview:self.mapView];
    }
    
    // Handle the callback when the GMTCMapView did initialized.
    
    -   (void)mapViewDidInitializeCustomerState:(GMTCMapView *)mapview {
      self.mapView.pickupLocation = self.selectedPickupLocation;
      self.mapView.dropoffLocation = self.selectedDropoffLocation;
    
      __weak __typeof(self) weakSelf = self;
      [self startTripBookingWithPickupLocation:self.selectedPickupLocation
                               dropoffLocation:self.selectedDropoffLocation
                                    completion:^(NSString *tripName, NSError *error) {
                                      __typeof(self) strongSelf = weakSelf;
                                      GMTCTripService *tripService = [GMTCServices sharedServices].tripService;
                                      // Create a tripModel instance for listening to updates to the trip specified by this trip name.
                                      GMTCTripModel *tripModel = [tripService tripModelForTripName:tripName];
                                      // Create a journeySharingSession instance based on the tripModel.
                                      GMTCJourneySharingSession *journeySharingSession =
                                        [[GMTCJourneySharingSession alloc] initWithTripModel:tripModel];
                                      // Add the journeySharingSession instance on the mapView for updating the UI.
                                      [strongSelf.mapView showMapViewSession:journeySharingSession];
                                      // Register for trip update events.
                                      [tripModel registerSubscriber:self];
    
                                      strongSelf.currentTripModel = tripModel;
                                      strongSelf.currentJourneySharingSession = journeySharingSession;
                                      [strongSelf hideLoadingView];
                                    }];
        [self showLoadingView];
    }
    

    سفر فعال را لغو کنید

    مثال زیر نحوه تنظیم مجدد سفر فعال فعلی را نشان می دهد.

    سریع

    /*
    
        *   MapViewController.swift
     */
    func cancelCurrentActiveTrip() {
      // Stop the tripModel
      self.currentTripModel.unregisterSubscriber(self)
    
      // Remove the journey sharing session from the mapView's UI stack.
      self.mapView.hide(journeySharingSession)
    }
    

    هدف-C

    /*
    
        *   MapViewController.m
     */
    -   (void)cancelCurrentActiveTrip {
      // Stop the tripModel
      [self.currentTripModel unregisterSubscriber:self];
    
      // Remove the journey sharing session from the mapView's UI stack.
      [self.mapView hideMapViewSession:journeySharingSession];
    }
    

    به به روز رسانی سفر گوش دهید

    مثال زیر نحوه ثبت callback tripModel را نشان می دهد.

    سریع

    /*
    
        *   MapViewController.swift
     */
    override func viewDidLoad() {
      super.viewDidLoad()
      // Register for trip update events.
      self.currentTripModel.register(self)
    }
    

    هدف-C

    /*
    
        *   MapViewController.m
     */
    -   (void)viewDidLoad {
      [super viewDidLoad];
      // Register for trip update events.
      [self.currentTripModel registerSubscriber:self];
      ...
    }
    

    مثال زیر نحوه لغو ثبت نام tripModel callback را نشان می دهد.

    سریع

    /*
    
        *   MapViewController.swift
     */
    deinit {
      self.currentTripModel.unregisterSubscriber(self)
    }
    

    هدف-C

    /*
    
        *   MapViewController.m
     */
    -   (void)dealloc {
      [self.currentTripModel unregisterSubscriber:self];
      ...
    }
    

    مثال زیر نحوه پیاده‌سازی پروتکل GMTCTripModelSubscriber را برای رسیدگی به تماس‌ها هنگام به‌روزرسانی وضعیت سفر نشان می‌دهد.

    سریع

    /*
    
        *   MapViewController.swift
     */
    func tripModel(_: GMTCTripModel, didUpdate trip: GMTSTrip?, updatedPropertyFields: GMTSTripPropertyFields) {
      // Update the UI with the new `trip` data.
      self.updateUI(with: trip)
    }
    
    func tripModel(_: GMTCTripModel, didUpdate tripStatus: GMTSTripStatus) {
      // Handle trip status did change.
    }
    
    func tripModel(_: GMTCTripModel, didUpdateActiveRouteRemainingDistance activeRouteRemainingDistance: Int32) {
      // Handle remaining distance of active route did update.
    }
    
    func tripModel(_: GMTCTripModel, didUpdateActiveRoute activeRoute: [GMTSLatLng]?) {
      // Handle trip active route did update.
    }
    
    func tripModel(_: GMTCTripModel, didUpdate vehicleLocation: GMTSVehicleLocation?) {
      // Handle vehicle location did update.
    }
    
    func tripModel(_: GMTCTripModel, didUpdatePickupLocation pickupLocation: GMTSTerminalLocation?) {
      // Handle pickup location did update.
    }
    
    func tripModel(_: GMTCTripModel, didUpdateDropoffLocation dropoffLocation: GMTSTerminalLocation?) {
      // Handle drop off location did update.
    }
    
    func tripModel(_: GMTCTripModel, didUpdatePickupETA pickupETA: TimeInterval) {
      // Handle the pickup ETA did update.
    }
    
    func tripModel(_: GMTCTripModel, didUpdateDropoffETA dropoffETA: TimeInterval) {
      // Handle the drop off ETA did update.
    }
    
    func tripModel(_: GMTCTripModel, didUpdateRemaining remainingWaypoints: [GMTSTripWaypoint]?) {
      // Handle updates to the pickup, dropoff or intermediate destinations of the trip.
    }
    
    func tripModel(_: GMTCTripModel, didFailUpdateTripWithError error: Error?) {
      // Handle the error.
    }
    
    func tripModel(_: GMTCTripModel, didUpdateIntermediateDestinations intermediateDestinations: [GMTSTerminalLocation]?) {
      // Handle the intermediate destinations being updated.
    }
    
    func tripModel(_: GMTCTripModel, didUpdateActiveRouteTraffic activeRouteTraffic: GMTSTrafficData?) {
      // Handle trip active route traffic being updated.
    }
    

    هدف-C

    /*
    
        *   MapViewController.m
     */
    #pragma mark - GMTCTripModelSubscriber implementation
    
    -   (void)tripModel:(GMTCTripModel *)tripModel
                didUpdateTrip:(nullable GMTSTrip *)trip
        updatedPropertyFields:(enum GMTSTripPropertyFields)updatedPropertyFields {
      // Update the UI with the new `trip` data.
      [self updateUIWithTrip:trip];
      ...
    }
    
    -   (void)tripModel:(GMTCTripModel *)tripModel didUpdateTripStatus:(enum GMTSTripStatus)tripStatus {
      // Handle trip status did change.
    }
    
    -   (void)tripModel:(GMTCTripModel *)tripModel
        didUpdateActiveRouteRemainingDistance:(int32_t)activeRouteRemainingDistance {
       // Handle remaining distance of active route did update.
    }
    
    -   (void)tripModel:(GMTCTripModel *)tripModel
        didUpdateActiveRoute:(nullable NSArray<GMTSLatLng *> *)activeRoute {
      // Handle trip active route did update.
    }
    
    -   (void)tripModel:(GMTCTripModel *)tripModel
        didUpdateVehicleLocation:(nullable GMTSVehicleLocation *)vehicleLocation {
      // Handle vehicle location did update.
    }
    
    -   (void)tripModel:(GMTCTripModel *)tripModel
        didUpdatePickupLocation:(nullable GMTSTerminalLocation *)pickupLocation {
      // Handle pickup location did update.
    }
    
    -   (void)tripModel:(GMTCTripModel *)tripModel
        didUpdateDropoffLocation:(nullable GMTSTerminalLocation *)dropoffLocation {
      // Handle drop off location did update.
    }
    
    -   (void)tripModel:(GMTCTripModel *)tripModel didUpdatePickupETA:(NSTimeInterval)pickupETA {
      // Handle the pickup ETA did update.
    }
    
    -   (void)tripModel:(GMTCTripModel *)tripModel
        didUpdateRemainingWaypoints:(nullable NSArray<GMTSTripWaypoint *> *)remainingWaypoints {
      // Handle updates to the pickup, dropoff or intermediate destinations of the trip.
    }
    
    -   (void)tripModel:(GMTCTripModel *)tripModel didUpdateDropoffETA:(NSTimeInterval)dropoffETA {
      // Handle the drop off ETA did update.
    }
    
    -   (void)tripModel:(GMTCTripModel *)tripModel didFailUpdateTripWithError:(nullable NSError *)error {
      // Handle the error.
    }
    
    -   (void)tripModel:(GMTCTripModel *)tripModel
        didUpdateIntermediateDestinations:
            (nullable NSArray<GMTSTerminalLocation *> *)intermediateDestinations {
      // Handle the intermediate destinations being updated.
    }
    
    -   (void)tripModel:(GMTCTripModel *)tripModel
        didUpdateActiveRouteTraffic:(nullable GMTSTrafficData *)activeRouteTraffic {
      // Handle trip active route traffic being updated.
    }
    

    رسیدگی به خطا

    اگر در tripModel مشترک شده‌اید و خطایی رخ می‌دهد، می‌توانید با اجرای روش delegate tripModel(_:didFailUpdateTripWithError:) پاسخ تماس tripModel را دریافت کنید. Fleet Engine پیام خطایی را ایجاد کرد که از استاندارد Google Cloud Error پیروی می کند. برای جزئیات تعریف پیام خطا و همه کدهای خطا به مستندات Google Cloud Errors مراجعه کنید.

    به طور خاص، برای نظارت بر سفر، نیاز به ارائه یک رمز تأیید اعتبار دارد. 401 UNAUTHENTICATED در صورتی که اعتبار احراز هویت معتبری وجود نداشته باشد، مانند رمز منقضی شده است، افزایش می یابد. 403 PERMISSION_DENIED در صورتی که تماس‌گیرنده مجوز فراخوانی یک api خاص را نداشته باشد (به عنوان مثال، کاربر با نقش مصرف‌کننده سعی می‌کند updateTrip را فراخوانی کند)، یا درخواست دارای شناسه/trip_id معتبر در JWT نباشد، افزایش می‌یابد.

    برای اطلاعات بیشتر، به مدیریت خطاهای SDK مصرف کننده مراجعه کنید.

    سفارشی سازی UI

    گزینه های رابط کاربری چند خطی سفارشی را دریافت و تنظیم کنید

    مثال زیر نحوه تنظیم گزینه های UI سفارشی برای چند خطوط را نشان می دهد.

    سریع

    /** MapViewController.swift */
    
    func updatePolylineUIOptions() {
      // The polyline type that you would like to set custom UI options for.
      let customizablePolylineType = GMTCPolylineType.activeRoute
    
      let polylineStyleOptions = GMTCMutablePolylineStyleOptions()
      polylineStyleOptions.strokeWidth = 8.0
      polylineStyleOptions.strokeColor = .blue
      polylineStyleOptions.isVisible = true
      polylineStyleOptions.zIndex = 1000
      polylineStyleOptions.isGeodesic = true
      let coordinator = self.mapView.consumerMapStyleCoordinator
      coordinator.setPolylineStyleOptions(polylineStyleOptions, polylineType:customizablePolylineType)
    }
    

    هدف-C

    /** MapViewController.m */
    
    -   (void)updatePolylineUIOptions {
      // The polyline type that you would like to set custom UI options for.
      GMTCPolylineType customizablePolylineType = GMTCPolylineTypeActiveRoute;
    
      GMTCMutablePolylineStyleOptions *polylineStyleOptions =
          [[GMTCMutablePolylineStyleOptions alloc] init];
      polylineStyleOptions.strokeWidth = 8.0;
      polylineStyleOptions.strokeColor = [UIColor blueColor];
      polylineStyleOptions.isVisible = YES;
      polylineStyleOptions.zIndex = 1000;
      polylineStyleOptions.isGeodesic = YES;
      [[_mapView consumerMapStyleCoordinator] setPolylineStyleOptions:polylineStyleOptions
                                                    polylineType:customizablePolylineType];
    }
    

    گزینه های رابط کاربری نشانگر سفارشی را دریافت و تنظیم کنید

    مثال زیر نحوه تنظیم گزینه های UI سفارشی برای نشانگرها را نشان می دهد.

    سریع

    /** MapViewController.swift */
    
    func updateMarkerUIOptions() {
      let customizableMarkerType = GMTCCustomizableMarkerType.tripVehicle
      let markerStyleOptions = GMTCMutableMarkerStyleOptions()
      markerStyleOptions.groundAnchor = groundAnchor
      markerStyleOptions.isVisible = true
      markerStyleOptions.icon = icon
      markerStyleOptions.zIndex = 100
      markerStyleOptions.isFlat = false
      let coordinator = self.mapView.consumerMapStyleCoordinator
      coordinator.setMarkerStyleOptions(markerStyleOptions, markerType: customizableMarkerType)
    }
    

    هدف-C

    /** MapViewController.m */
    
    -   (void)updateMarkerUIOptions {
      // The marker type that you would like to set custom UI options for.
      GMTCCustomizableMarkerType customizableMarkerType = GMTCCustomizableMarkerTypeTripVehicle;
    
      GMTCMutableMarkerStyleOptions *markerStyleOptions =
          [[GMTCMutableMarkerStyleOptions alloc] init];
      markerStyleOptions.groundAnchor = groundAnchor;
      markerStyleOptions.isVisible = YES;
      markerStyleOptions.icon = icon;
      markerStyleOptions.zIndex = 100;
      markerStyleOptions.isFlat = NO;
    
      [[_mapView consumerMapStyleCoordinator] setMarkerStyleOptions:markerStyleOptions markerType:customizableMarkerType];
    }
    

    تنظیم زوم دوربین

    دکمه موقعیت مکانی من در Maps SDK برای iOS دوربین را روی مکان دستگاه متمرکز می کند.

    اگر جلسه اشتراک‌گذاری سفر فعالی وجود دارد، می‌توانید دوربین را در مرکز قرار دهید تا به جای تمرکز بر روی مکان دستگاه، روی سفر متمرکز شود.

    Consumer SDK یک ویژگی دوربین خودکار را ارائه می دهد که به طور پیش فرض فعال است. دوربین بزرگنمایی می کند تا روی مسیر اشتراک گذاری سفر و ایستگاه بعدی سفر تمرکز کند.

    دوربین خودکار

    اگر به کنترل بیشتری بر رفتار دوربین نیاز دارید، می‌توانید ویژگی دوربین خودکار را با استفاده از ویژگی isAllowCameraAutoUpdate غیرفعال یا فعال کنید.

    برای سفارشی‌سازی‌های بیشتر دوربین، Maps SDK for iOS را ببینید حرکت دوربین .