オンデマンド配車および配達ソリューションは現在、一部のパートナー様のみご利用いただけます。

Consumer SDK for iOS スタートガイド

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

Consumer SDK を使用すると、オンデマンド配車および配達ソリューションのバックエンド サービスと統合した基本的なコンシューマー アプリをビルドして実行できます。アクティブなルートを表示し、ルートの更新情報に対応し、ルートエラーを処理できる Trip and Order Progress アプリを作成できます。

コンシューマ SDK にはモジュール アーキテクチャがあるため、特定のアプリで使用する API のパーツを使用して、独自の API、Fleet Engine が提供するバックエンド サービス、Google Maps Platform の追加 API と統合できます。

最小システム要件

  • モバイル デバイスが iOS 12 以降を搭載している必要があります。
  • Xcodeバージョン 13 以降。
  • プロジェクト構成

    Consumer SDK を構成するには、CocoaPods を使用します。

    CocoaPods を使用

    CocoaPods を使用してコンシューマ SDK を構成するには、次の項目が必要です。

    • CocoaPods ツール: このツールをインストールするには、ターミナルを開いて次のコマンドを実行します。

      sudo gem install cocoapods
      

      詳細については、CocoaPods スタートガイドをご覧ください。

    • Google アクセスリストに記載されている開発用アカウント。この SDK の Pod リポジトリは公開ソースではありません。この Pod にアクセスするには、Google カスタマー エンジニアにお問い合わせください。エンジニアが、開発用アカウントをアクセスリストに追加し、認証用に Cookie を設定します。

    プロジェクトがアクセスリストに表示されると、Pod にアクセスできるようになります。

    1. Consumer SDK の Podfile を作成し、それを使用して API とその依存関係をインストールします。まず、プロジェクト ディレクトリに Podfile という名前のファイルを作成します。このファイルは、プロジェクトの依存関係を定義します。次に、Podfile を編集して、依存関係を追加します。依存関係を含む例を次に示します。

      source "https://cpdc-eap.googlesource.com/ridesharing-consumer-sdk"
      source "https://github.com/CocoaPods/Specs.git"
      
      target 'YOUR_APPLICATION_TARGET_NAME_HERE' do
        pod 'GoogleRidesharingConsumer'
      end
      
    2. Podfile を保存します。ターミナルを開いて、Podfile があるディレクトリに移動します。

      cd <path-to-project>
      
    3. Pod のインストール コマンドを実行します。これにより、Podfile で指定された API と、それらの依存関係(存在する場合)がインストールされます。

      pod install
      
    4. Xcode を閉じてから、プロジェクトの .xcworkspace ファイルを開いて(ダブルクリックして)Xcode を起動します。後でプロジェクトを開くには、.xcworkspace ファイルを使用します。

    XCFramework をインストールする

    XCFramework は、コンシューマ SDK のインストールに使用するバイナリ パッケージです。このパッケージは、M1 チップセットを使用しているマシンを含む複数のプラットフォームで使用できます。このガイドでは、コンシューマ SDK を含む XCFramework をプロジェクトに手動で追加し、Xcode でビルド設定を構成する方法について説明します。

    1. Google から受け取ったソースファイルを展開します。

    2. Xcode を起動し、既存のプロジェクトを開くか、新しいプロジェクトを作成します。iOS を初めて使用する場合は、新しいプロジェクトを作成し、iOS アプリ テンプレートを選択します。

    3. プロジェクト グループの下にフレームワーク グループがまだ存在しない場合は、作成します。

    4. XCFramework を含む zip の Resources ディレクトリに含まれる gRPCCertificates.bundle ファイルを、Xcode プロジェクトの最上位ディレクトリにドラッグします。画面の指示に沿って、必要に応じて [アイテムをコピー] を選択します。

    5. Consumer SDK をインストールするには、GoogleRidesharingConsumer.xcframework ファイルを Frameworks, Libraries, and Embedded Content の下のプロジェクトにドラッグします。画面の指示に沿って、必要に応じて [アイテムをコピー] を選択します。

    6. Project Navigator のプロジェクトを選択し、アプリのターゲットを選択します。

    7. [Build Phases] タブを開き、[Link Binary with Libraries] に、次のフレームワークとライブラリを追加します(まだ存在しない場合)。

      • 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 を追加します。これらの設定が表示されていない場合は、[Build Settings] バーのフィルタを [Basic] から [All] に変更します。

    アプリケーションの統合

    認証トークンを指定する

    コンシューマ アプリが Fleet Engine にルートの更新をリクエストする場合、リクエストに有効なアクセス トークンを含める必要があります。これらのリクエストを認可して認証するため、Consumer SDK は GMTCAuthorization プロトコルに準拠したオブジェクトを呼び出します。オブジェクトは、必要なアクセス トークンを提供する役割を担います。

    トークンの生成方法はアプリ デベロッパーが選択します。実装では、次の処理を行う必要があります。

    • HTTPS サーバーからアクセス トークンを(場合によっては JSON 形式で)フェッチします。
    • トークンを解析し、キャッシュに保存します。
    • 有効期限が切れたらトークンを更新します。

    Fleet Engine サーバーで想定されるトークンの詳細については、認可用の JSON ウェブトークン(JWT)の作成をご覧ください。

    プロバイダ ID は、Google Cloud プロジェクト ID と同じです。詳細については、Fleet Engine を使ってみるをご覧ください。

    次の例では、アクセス トークン プロバイダを実装しています。

    Swift

    /*
     * 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()
      }
    }
    

    Objective-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
    

    アプリケーションの初期化

    Swift

    /*
     * 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
      }
    }
    

    Objective-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 を初期化する方法を示しています。

    Swift

    /*
     * 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!)
        ...
      }
    

    Objective-C

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

    地図表示イベントを処理する

    次の例は、顧客状態イベントを処理するデリゲートを実装する方法を示しています。

    Swift

    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.
    }
    

    Objective-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 を作成して工程の共有を直接開始できます。

    Swift

    /*
     * 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()
    }
    

    Objective-C

    /*
     * MapViewController.m
     */
    - (void)viewDidLoad {
      [super viewDidLoad];
      ...
      self.mapView = [[GMTCMapView alloc] init];
      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];
    }
    

    有効なルートをキャンセル

    次の例は、現在アクティブなルートをリセットする方法を示しています。

    Swift

    /*
     * 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)
    }
    

    Objective-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];
    }
    

    ルートの更新情報を確認

    次の例は、tripModel コールバックの登録方法を示しています。

    Swift

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

    Objective-C

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

    次の例は、tripModel コールバックの登録をキャンセルする方法を示しています。

    Swift

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

    Objective-C

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

    次の例は、ルートの状態が更新されたときにコールバックを処理する GMTCTripModelSubscriber プロトコルを実装する方法を示しています。

    Swift

    /*
     * 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.
    }
    

    Objective-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 を登録してエラーが発生した場合は、委譲メソッド tripModel(_:didFailUpdateTripWithError:) を実装することで tripModel のコールバックを取得できます。Fleet Engine は、Google Cloud Error Standard に沿ったエラー メッセージを生成しました。エラー メッセージの定義とすべてのエラーコードの詳細については、Google Cloud のエラーに関するドキュメントをご覧ください。

    具体的には、ルート モニタリングの場合は、有効な認証トークンを提供する必要があります。401 UNAUTHENTICATED は、トークンが期限切れなど、有効な認証情報がない場合に送出されます。403 PERMISSION_DENIED呼び出し元に特定の API を呼び出す権限がない場合(たとえば、コンシューマ ロールを持つユーザーが updateTrip を呼び出そうと試みた場合)、JWT トークンに有効な Vehicle_id/trip_id がない場合に送出されます。

    詳細については、Consumer SDK のエラー処理をご覧ください。

    UI のカスタマイズ

    カスタム ポリライン UI オプションの取得または設定

    次の例は、ポリラインにカスタム UI オプションを設定する方法を示しています。

    Swift

    /** 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)
    }
    

    Objective-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 オプションの取得または設定

    次の例は、マーカーのカスタム UI オプションを設定する方法を示しています。

    Swift

    /** 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)
    }
    

    Objective-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 for iOS の現在地ボタンでは、デバイスの現在地をカメラの中心に設定します。

    アクティブなジャーニー共有セッションがある場合は、デバイスの位置情報だけでなく、ジャーニーにカメラを集中させることができます。

    Consumer SDK には、デフォルトで有効になっている自動カメラ機能が用意されています。移動経路と次のルートの地点にズームしてズームします。

    自動カメラ

    カメラの動作をより詳細に制御する必要がある場合は、isAllowCameraAutoUpdate プロパティを使用して自動カメラ機能を無効または有効にすることができます。

    カメラのカスタマイズについて詳しくは、Maps SDK for iOS のカメラ移動をご覧ください。