Вы можете использовать Consumer SDK для создания и запуска базового потребительского приложения, интегрированного с серверными службами решения On-demand Rides and Delivery Solution. Вы можете создать приложение «Прогресс поездки и заказа», которое может отображать активную поездку, реагировать на обновления поездки и обрабатывать ошибки поездки.
Поскольку Consumer SDK имеет модульную архитектуру, вы можете использовать те части API, которые хотите использовать для своего конкретного приложения, и интегрировать их со своими собственными API, серверными службами, предоставляемыми Fleet Engine, и дополнительными API платформы Google Maps. .
Минимальные системные требования
Конфигурация проекта
Менеджер пакетов Swift
Consumer SDK можно установить через Swift Package Manager . Чтобы добавить SDK, убедитесь, что вы удалили все существующие зависимости Consumer SDK.
Чтобы добавить SDK в новый или существующий проект, выполните следующие действия:
- Откройте
project
илиworkspace
Xcode, затем выберите «Файл» > «Добавить зависимости пакета» . - Введите https://github.com/googlemaps/ios-consumer-sdk в качестве URL-адреса, нажмите Enter , чтобы получить пакет, и нажмите «Добавить пакет».
- Чтобы установить конкретную
version
, установите в поле «Правило зависимости» один из вариантов, зависящих от версии. Для новых проектов рекомендуем указывать последнюю версию и использовать опцию «Точная версия». После завершения нажмите «Добавить пакет». - В окне «Выбор пакетных продуктов» убедитесь, что
GoogleRidesharingConsumer
будет добавлен к назначенной вамиmain
цели. После завершения нажмите «Добавить пакет». - Чтобы проверить установку, перейдите на панель
General
» целевой системы. В разделе «Платформы», «Библиотеки» и «Встроенный контент» вы должны увидеть установленные пакеты. Вы также можете просмотреть раздел «Зависимости пакетов» в «Навигаторе проекта», чтобы проверить пакет и его версию.
Чтобы обновить package
для существующего проекта, выполните следующие действия:
Если вы выполняете обновление с версии более ранней, чем 9.0.0, после обновления необходимо удалить следующие зависимости:
GoogleMapsBase
,GoogleMapsCore
иGoogleMapsM4B
. Не удаляйте зависимость дляGoogleMaps
. Дополнительную информацию см. в примечаниях к выпуску версии 9.0.0 .В настройках конфигурации проекта Xcode найдите Frameworks, Libraries и Embedded Content . Используйте знак минус (-), чтобы удалить следующую структуру:
-
GoogleMapsBase
(только для обновлений с версий ранее 9.0.0) -
GoogleMapsCore
(только для обновлений с версий ранее 9.0.0) -
GoogleMapsM4B
(только для обновлений с версий ранее 9.0.0)
-
- В Xcode перейдите в «Файл» > «Пакеты» > «Обновить до последних версий пакетов».
- Чтобы проверить установку, перейдите в раздел «Зависимости пакетов» в «Навигаторе проекта» , чтобы проверить пакет и его версию.
Чтобы удалить существующие зависимости Consumer SDK, добавленные с помощью CocoaPods
, выполните следующие действия:
- Закройте рабочую область Xcode. Откройте терминал и выполните следующую команду:
sudo gem install cocoapods-deintegrate cocoapods-clean pod deintegrate pod cache clean --all
- Удалите
Podfile
,Podfile.resolved
иworkspace
Xcode, если вы не используете их ни для чего, кроме CocoaPods.
Чтобы удалить существующий Consumer SDK, установленный вручную, выполните следующие действия:
В настройках конфигурации проекта Xcode найдите Frameworks, Libraries и Embedded Content . Используйте знак минус
(-)
, чтобы удалить следующую структуру:-
GoogleRidesharingConsumer.xcframework
-
Из каталога верхнего уровня вашего проекта Xcode удалите пакет
GoogleRidesharingConsumer
.
Какао-стручки
Чтобы настроить Consumer SDK с использованием CocoaPods, вам потребуются следующие элементы:
Инструмент CocoaPods: Чтобы установить этот инструмент, откройте Терминал и выполните следующую команду.
sudo gem install cocoapods
Дополнительные сведения см. в руководстве по началу работы с CocoaPods .
Создайте подфайл для Consumer SDK и используйте его для установки API и его зависимостей. Сначала создайте файл с именем Podfile в каталоге вашего проекта. Этот файл определяет зависимости вашего проекта. Затем отредактируйте подфайл и добавьте свои зависимости. Вот пример, который включает зависимости:
source "https://github.com/CocoaPods/Specs.git" target 'YOUR_APPLICATION_TARGET_NAME_HERE' do pod 'GoogleRidesharingConsumer' end
Сохраните подфайл. Откройте терминал и перейдите в каталог, содержащий подфайл:
cd <path-to-project>
Запустите команду установки модуля. При этом будут установлены API, указанные в подфайле, а также все зависимости, которые они могут иметь.
pod install
Закройте Xcode, а затем откройте (дважды щелкните) файл .xcworkspace вашего проекта, чтобы запустить Xcode. Чтобы открыть проект позже, используйте файл .xcworkspace.
Ручная установка
XCFramework — это двоичный пакет, который вы используете для установки Consumer SDK. Вы можете использовать этот пакет на нескольких платформах, включая машины, использующие набор микросхем M1. В этом руководстве показано, как вручную добавить XCFramework, содержащий Consumer SDK, в ваш проект и настроить параметры сборки в Xcode.
Загрузите двоичный файл SDK и ресурсы:
Распакуйте заархивированные файлы, чтобы получить доступ к XCFramework и ресурсам.
Запустите Xcode и либо откройте существующий проект, либо создайте новый проект. Если вы новичок в iOS, создайте новый проект и выберите шаблон приложения iOS.
Создайте группу Frameworks в группе проекта, если она еще не существует.
Чтобы установить Consumer SDK, перетащите файл
GoogleRidesharingConsumer.xcframework
в свой проект в разделе Frameworks, Libraries и Embedded Content . При появлении запроса выберите Копировать элементы, если необходимо.Перетащите загруженный файл
GoogleRidesharingConsumer.bundle
в каталог верхнего уровня вашего проекта Xcode. При появлении запроса выберитеCopy items if needed
.Выберите свой проект в Навигаторе проектов и выберите цель своего приложения.
Откройте вкладку «Фазы сборки» и в разделе «Связывание двоичных файлов с библиотеками» добавьте следующие платформы и библиотеки, если они еще не присутствуют:
-
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
-
Выберите свой проект, а не конкретную цель, и откройте вкладку «Настройки сборки» . В разделе «Другие флаги компоновщика» добавьте
-ObjC
как для отладки, так и для выпуска. Если эти настройки не отображаются, измените фильтр на панели «Параметры сборки» с «Базовый» на «Все» .
Проверьте файл манифеста конфиденциальности Apple.
Apple требует предоставить информацию о конфиденциальности для приложений в App Store. Посетите страницу сведений о конфиденциальности Apple App Store для получения обновлений и дополнительной информации.
Файл манифеста конфиденциальности Apple включен в пакет ресурсов для SDK. Чтобы убедиться, что файл манифеста конфиденциальности включен, и проверить его содержимое, создайте архив своего приложения и создайте отчет о конфиденциальности из архива.
Интеграция приложений
Предоставьте токен аутентификации
Когда ваше потребительское приложение запрашивает обновления о поездках от 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];
}
Слушайте новости о поездках
В следующем примере показано, как зарегистрировать обратный вызов 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
.
Быстрый
/*
* 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 и возникла ошибка, вы можете получить обратный вызов tripModel, реализовав метод делегата tripModel(_:didFailUpdateTripWithError:)
. Fleet Engine выдал сообщение об ошибке, соответствующее стандарту ошибок Google Cloud. Подробное определение сообщения об ошибке и все коды ошибок см. в документации Google Cloud Errors .
В частности, для мониторинга поездок требуется предоставить действительный токен аутентификации. 401 UNAUTHENTICATED
будет возникать, если нет действительных учетных данных для аутентификации, например, срок действия токена истек. 403 PERMISSION_DENIED
будет возникать, если у вызывающего абонента нет разрешения на вызов определенного API (например, пользователь с ролью потребителя пытается вызвать updateTrip) или в запросе нет допустимого транспортного средства/trip_id в токене JWT.
Дополнительные сведения см. в разделе Обработка ошибок Consumer SDK .
Настройка пользовательского интерфейса
Получение и установка пользовательских параметров пользовательского интерфейса полилинии
В следующем примере показано, как задать пользовательские параметры пользовательского интерфейса для полилиний.
Быстрый
/** 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];
}
Получение и установка параметров пользовательского интерфейса маркера
В следующем примере показано, как установить пользовательские параметры пользовательского интерфейса для маркеров.
Быстрый
/** 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 для iOS. Перемещение камеры .