您可以使用使用方 SDK 构建并运行基本的 集成了按需行程和交付解决方案后端服务的消费者应用。您可以 创建一个可显示有效行程的“行程和订单进度”应用, 响应行程更新和处理行程错误。
由于消费者 SDK 采用模块化架构 您可以针对您的特定应用使用 API 的相应部分, 将它们与您自己的 API、由舰队提供的后端服务集成 和 Google Maps Platform 的其他 API。
最低系统要求
项目配置
Swift Package Manager
消费者 SDK 可通过 Swift Package Manager 的相关文档。要添加 SDK,请确保您已 移除了所有现有的使用方 SDK 依赖项。
如需将 SDK 添加到新项目或现有项目,请按以下步骤操作:
-
打开 Xcode
project
或workspace
,然后转到 File >添加软件包依赖项。 - 输入 https://github.com/googlemaps/ios-consumer-sdk 作为网址,然后按 Enter 键 以提取软件包,然后点击“Add Package”(添加软件包)。
-
如需安装特定的
version
,请将 Dependency Rule 字段设置为以下其中一项: 基于版本的选项对于新项目,我们建议您指定最新版本和 使用“确切版本”选项。完成后,点击“添加软件包”。 -
在 Choose Package Products(选择软件包产品)窗口中,验证
GoogleRidesharingConsumer
是否已添加到 您指定的main
目标。完成后,点击“添加软件包”。 -
如需验证安装,请前往目标的
General
窗格。 在框架、库和嵌入式内容中,您应该会看到已安装的软件包。 您还可以查看“Package Dependencies”“Project Navigator”部分 以验证软件包及其版本。
如需更新现有项目的 package
,请按以下步骤操作:
如果您要从 9.0.0 之前的版本升级,就必须移除 以下依赖项:
GoogleMapsBase
、GoogleMapsCore
和GoogleMapsM4B
。请勿移除GoogleMaps
。有关详情,请参阅 9.0.0 版版本说明。在您的 Xcode 项目配置设置中,找到 Frameworks, Libraries, 和嵌入式内容。使用减号(-) 移除以下框架:
GoogleMapsBase
(仅适用于从 9.0.0 之前的版本进行的升级)GoogleMapsCore
(仅适用于从 9.0.0 之前的版本进行的升级)GoogleMapsM4B
(仅适用于从 9.0.0 之前的版本进行的升级)
- 在 Xcode 中,转到“File”(文件)>文件包 >更新到最新的软件包版本”。
- 如需验证安装,请前往 Project Navigator 的 Package Dependencies 部分 以验证软件包及其版本。
如需移除使用以下代码添加的现有使用方 SDK 依赖项,请执行以下操作:
CocoaPods
,请按以下步骤操作:
- 关闭 Xcode 工作区。打开终端并执行以下命令:
sudo gem install cocoapods-deintegrate cocoapods-clean pod deintegrate pod cache clean --all
-
移除
Podfile
、Podfile.resolved
和 Xcodeworkspace
(如果您不将其用于 CocoaPods 之外的任何其他用途)。
如需移除已安装的现有消费者 SDK 请按照以下步骤操作:
在您的 Xcode 项目配置设置中,找到 Frameworks, 库和嵌入式内容。使用减号
(-)
移除 以下框架:GoogleRidesharingConsumer.xcframework
从 Xcode 项目的顶级目录中,删除
GoogleRidesharingConsumer
个套装。
CocoaPods
要使用 CocoaPods 配置使用方 SDK, 需要以下各项:
CocoaPods 工具:要安装此工具,请打开终端并运行 。
sudo gem install cocoapods
请参阅 CocoaPods 使用入门 指南,了解更多信息 。
为使用方 SDK 创建一个 Podfile 并使用它 安装 API 及其依赖项。首先,创建一个名为 Podfile此文件定义项目的 依赖项然后修改 Podfile 并添加依赖项。以下是 一个包含依赖项的示例:
source "https://github.com/CocoaPods/Specs.git" target 'YOUR_APPLICATION_TARGET_NAME_HERE' do pod 'GoogleRidesharingConsumer' end
保存 Podfile。打开终端并转到包含 Podfile:
cd <path-to-project>
运行 pod install 命令。这会安装 Podfile 及其可能具有的任何依赖项。
pod install
关闭 Xcode,然后打开(双击)您项目的 .xcworkspace 启动 Xcode。如需稍后打开项目,请使用 .xcworkspace 文件。
手动安装
XCFramework 是一个二进制包,用于将 使用方 SDK。你可以将此软件包用于 包括使用 M1 芯片组的机器。本指南介绍了如何 手动添加包含 使用方 SDK 添加到您的项目中,并配置 构建设置
下载 SDK 二进制文件和资源:
解压缩压缩文件以访问 XCFramework 和资源。
启动 Xcode,并打开现有项目或创建新项目 项目。如果您是第一次使用 iOS,请创建一个新项目,并选择 iOS 应用模板。
在项目组下创建一个框架组(如果不存在) 。
如需安装使用方 SDK,请将
GoogleRidesharingConsumer.xcframework
文件拖动到项目中的框架、库和嵌入式内容下。出现提示时,选择 根据需要复制项目 (Copy items if needed)。将下载的
GoogleRidesharingConsumer.bundle
拖动到 Xcode 项目的顶层目录中。出现提示时,选择Copy items if needed
。从项目导航器中选择您的项目,然后选择 应用的目标
打开“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
选择您的项目(而不是特定目标),然后打开 Build 设置标签页。在 Other Linker Flags(其他链接器标记)部分中,添加
-ObjC
调试和发布。如果看不到这些设置,请更改 “Build Settings”(构建设置)栏中将过滤条件从“Basic”(基本)更改为“All”(全部)。
检查 Apple 隐私清单文件
Apple 要求为 App Store 中的应用提供应用隐私权详细信息。如需了解最新动态和更多信息,请访问 Apple App Store 隐私权详情页面。
Apple 隐私清单文件包含在 SDK 的资源包中。如需验证隐私清单文件是否包含在内并检查其内容,请创建应用的归档,并从归档中生成隐私报告。
应用集成
提供身份验证令牌
当您的消费者应用从 Fleet Engine 请求行程更新时,请求
必须包含有效的访问令牌。如需对这些请求进行授权和身份验证,请按以下步骤操作:
使用方 SDK 调用符合
GMTCAuthorization
协议。对象负责提供
所需的访问令牌。
作为应用开发者,您可以选择令牌的生成方式。您的实现 应能够执行以下操作:
- 从 HTTPS 服务器提取访问令牌(可能是 JSON 格式)。
- 解析并缓存令牌。
- 在令牌过期时刷新。
如需详细了解 Fleet Engine 服务器预期的令牌,请参阅创建 JSON Web 令牌 (JWT) 授权。
提供方 ID 与 Google Cloud 项目 ID 相同。如需更多信息 请参阅舰队使用入门 引擎。
以下示例实现了访问令牌提供程序:
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] initWithFrame:CGRectZero];
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] 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];
}
取消当前的行程
以下示例展示了如何重置当前进行中的行程。
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,但发生了错误,您可以获取
通过实现 delegate 方法实现 TripModel
tripModel(_:didFailUpdateTripWithError:)
。Fleet Engine 生成了错误
消息,遵循 Google Cloud Error 标准。对于详细错误
消息定义,并且所有错误代码都请参阅 Google Cloud 错误
文档。
具体而言,对于行程监控,它要求提供有效的身份验证
令牌。如果没有有效的身份验证,将引发 401 UNAUTHENTICATED
如令牌过期,则系统会抛出403 PERMISSION_DENIED
。
调用方无权调用特定 API(例如,使用使用方 API
角色尝试调用 updateTrip),或者请求没有有效的 vehicle_id/trip_id
请求令牌的令牌。
如需了解详情,请参阅使用方 SDK 错误 处理。
界面自定义
获取和设置自定义多段线界面选项
以下示例展示了如何为多段线设置自定义界面选项。
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];
}
获取和设置自定义标记界面选项
以下示例展示了如何为标记设置自定义界面选项。
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 中,将镜头置于设备位置的中心。
如果有正在进行的“历程分享”会话,您可以将摄像头置于画面中央, 将注意力集中在旅程上,而不是仅局限于设备位置。
消费者 SDK 提供自动相机功能, 默认处于启用状态相机会缩放,以聚焦于行程分享路线 下一个行程航点。
如果您需要进一步控制相机行为,可以停用或启用
使用
isAllowCameraAutoUpdate
属性。
有关镜头自定义的更多方法,请参阅Maps SDK for iOS 相机。