دنبال کردن سفر در iOS

انتخاب پلاتفرم: Android iOS JavaScript

وقتی سفری را دنبال می‌کنید، برنامه مصرف‌کننده شما مکان خودرو مناسب را به مصرف‌کننده نشان می‌دهد. برای انجام این کار، برنامه شما باید دنبال کردن سفر را شروع کند، پیشرفت سفر را به‌روز کند، و وقتی سفر تکمیل شد دنبال کردن آن را متوقف کند.

این سند نحوه عملکرد این فرایند را پوشش می‌دهد.

شروع دنبال کردن سفر

در اینجا نحوه شروع دنبال کردن سفر آمده است:

  • همه ورودی‌های کاربر مثل مکان‌های تحویل و دریافت را از 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()
}

آبجکتیو-سی

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

آبجکتیو-سی

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

آبجکتیو-سی

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

مثال توقف شنیدن به‌روزرسانی‌ها

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

Swift

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

آبجکتیو-سی

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

آبجکتیو-سی

/*
 * 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 را دریافت کنید. پیام‌های خطا از استاندارد خطای Google Cloud پیروی می‌کنند. برای مشاهده تعاریف دقیق پیام خطا و همه کدهای خطا، به اسناد خطاهای Google Cloud مراجعه کنید.

در اینجا برخی‌از خطاهای رایجی که ممکن است درطول پایش سفر رخ دهد آورده شده است:

HTTP RPC شرح
۴۰۰ INVALID_ARGUMENT کارخواه نام سفر نامعتبری را مشخص کرده است. نام سفر باید از قالب providers/{provider_id}/trips/{trip_id} پیروی کند. provider_id باید شناسه پروژه Cloud متعلق به ارائه‌دهنده خدمات باشد.
401 اصالت‌سنجی‌نشده اگر اطلاعات اعتباری اصالت‌سنجی معتبری وجود نداشته باشد، این خطا را دریافت می‌کنید. برای مثال، اگر نشان JWT بدون شناسه سفر امضا شده باشد یا نشان JWT منقضی شده باشد.
403 PERMISSION_DENIED اگر مشتری اجازه کافی نداشته باشد (برای مثال، کاربری با نقش مصرف‌کننده سعی کند updateTrip را فراخوانی کند)، اگر نشان JWT نامعتبر باشد، یا اگر API برای پروژه مشتری فعال نباشد، این خطا را دریافت می‌کنید. ممکن است کد JWT وجود نداشته باشد یا کد با شناسه سفری امضا شده باشد که با شناسه سفر درخواست‌شده مطابقت ندارد.
429 RESOURCE_EXHAUSTED سهمیه منبع صفر است یا نرخ ترافیک از حد مجاز فراتر رفته است.
۵۰۳ دردسترس نیست سرویس دردسترس نیست. معمولاً سرور ازکار افتاده است.
504 DEADLINE_EXCEEDED مهلت درخواست تمام شد. این خطا فقط زمانی رخ می‌دهد که تماس‌گیرنده مهلتی را تعیین کند که کوتاه‌تر از مهلت پیش‌فرض روش باشد (یعنی مهلت درخواست‌شده برای پردازش درخواست توسط سرور کافی نباشد) و درخواست در مهلت مقرر تکمیل نشود.

مدیریت خطاهای «کیت توسعه نرم‌افزار مصرف‌کننده»

«کیت توسعه نرم‌افزار مصرف‌کننده» خطاهای به‌روزرسانی سفر را بااستفاده از سازوکار بازخوانی به برنامه مصرف‌کننده ارسال می‌کند. پارامتر تماس برگشتی نوع برگشتی مختص پلاتفرم است ( TripUpdateError در Android، و NSError در iOS).

استخراج کدهای وضعیت

خطاهای منتقل‌شده به برگشتی معمولاً خطاهای gRPC هستند و می‌توانید اطلاعات تکمیلی را نیز به‌صورت کد وضعیت از آن‌ها استخراج کنید. برای فهرست کامل کدهای وضعیت، کدهای وضعیت و استفاده از آن‌ها در gRPC را ببینید.

Swift

‫NSError تا tripModel(_:didFailUpdateTripWithError:) دیگر فراخوانده می‌شود.

// Called when there is a trip update error.
func tripModel(_ tripModel: GMTCTripModel, didFailUpdateTripWithError error: Error?) {
  // Check to see if the error comes from gRPC.
  if let error = error as NSError?, error.domain == "io.grpc" {
    let gRPCErrorCode = error.code
    ...
  }
}

آبجکتیو-سی

‫NSError تا tripModel:didFailUpdateTripWithError: دیگر فراخوانده می‌شود.

// Called when there is a trip update error.
- (void)tripModel:(GMTCTripModel *)tripModel didFailUpdateTripWithError:(NSError *)error {
  // Check to see if the error comes from gRPC.
  if ([error.domain isEqualToString:@"io.grpc"]) {
    NSInteger gRPCErrorCode = error.code;
    ...
  }
}

تفسیر کدهای وضعیت

کدهای وضعیت دو نوع خطا را پوشش می‌دهند: خطاهای مربوط به سرور و شبکه، و خطاهای سمت کارخواه.

خطاهای سرور و شبکه

کدهای وضعیت زیر مربوط به خطاهای شبکه یا سرور هستند و برای حل آن‌ها نیازی به انجام هیچ اقدامی ندارید. «کیت توسعه نرم‌افزار مصرف‌کننده» به‌طور خودکار از آن‌ها بازیابی می‌شود.

رمز وضعیتشرح
لغو شد سرور ارسال پاسخ را متوقف کرد. این مشکل معمولاً به‌دلیل مشکل سرور رخ می‌دهد.
لغو شد سرور پاسخ خروجی را خاتمه داد. این اتفاق معمولاً زمانی رخ می‌دهد که
برنامه به پس‌زمینه ارسال می‌شود، یا زمانی که وضعیت در
برنامه «مصرف‌کننده» تغییر می‌کند.
قطع‌شده
DEADLINE_EXCEEDED پاسخ دادن سرور خیلی طول کشید.
دردسترس نیست سرور دردسترس نبود. این مشکل معمولاً به‌دلیل مشکل شبکه رخ می‌دهد.

خطاهای کارخواه

کدهای وضعیت زیر مربوط به خطاهای کارخواه است و باید برای رفع آن‌ها اقدام کنید. «کیت توسعه نرم‌افزار مصرف‌کننده» تا زمانی که هم‌رسانی سفر را پایان دهید، به تلاش مجدد برای بازآوری سفر ادامه می‌دهد، اما تا زمانی که اقدامی انجام ندهید، بازیابی نخواهد شد.

کد وضعیتشرح
INVALID_ARGUMENT برنامه «مصرف‌کننده» نام سفر نامعتبری را مشخص کرده است؛ نام سفر باید از قالب providers/{provider_id}/trips/{trip_id} پیروی کند.
NOT_FOUND سفر هرگز ایجاد نشده است.
PERMISSION_DENIED برنامه «مصرف‌کننده» اجازه‌های کافی ندارد. این خطا زمانی رخ می‌دهد که:
  • برنامه «مصرف‌کننده» اجازه ندارد
  • «کیت توسعه نرم‌افزار مصرف‌کننده» برای پروژه در «کنسول Google Cloud» فعال نشده است.
  • کد JWT وجود ندارد یا نامعتبر است.
  • ژتون JWT با شناسه سفری امضا شده است که با سفر درخواست‌شده مطابقت ندارد.
RESOURCE_EXHAUSTED سهمیه منبع صفر است یا نرخ جریان ترافیک از حد سرعت فراتر رفته است.
اصالت‌سنجی‌نشده درخواست به‌دلیل نامعتبر بودن نمودار اصالت‌سنجی ناموفق بود. این خطا زمانی رخ می‌دهد که نشان JWT بدون شناسه سفر امضا شده باشد، یا زمانی که نشان JWT منقضی شده باشد.