الإكمال التلقائي للأماكن

اختيار النظام الأساسي: Android iOS JavaScript خدمة الويب

تعرض خدمة الإكمال التلقائي في حزمة تطوير برامج الأماكن لأجهزة iOS قائمة بالتنبؤات استجابةً لطلبات بحث المستخدم. أثناء كتابة المستخدم، تعرض خدمة الإكمال التلقائي اقتراحات لأماكن مثل الأنشطة التجارية والعناوين ورموز المواقع المفتوحة ونقاط الاهتمام.

يمكنك إضافة ميزة الإكمال التلقائي إلى تطبيقك بالطرق التالية:

إضافة عنصر تحكُّم في واجهة المستخدم للإكمال التلقائي

عنصر التحكم في واجهة مستخدم الإكمال التلقائي هو مربع حوار بحث مزود بوظيفة الإكمال التلقائي المدمجة. عندما يُدخِل أحد المستخدمين عبارات بحث، يعرض عنصر التحكم قائمة بالأماكن المتوقّعة للاختيار من بينها. عندما يختار المستخدم، يتم عرض مثيل GMSPlace، يمكن لتطبيقك بعد ذلك استخدامه للحصول على تفاصيل حول المكان الذي تم اختياره.

يمكنك إضافة عنصر تحكم الإكمال التلقائي في واجهة المستخدم إلى تطبيقك بالطرق التالية:

إضافة عنصر تحكُّم بملء الشاشة

يمكنك استخدام عنصر التحكّم بملء الشاشة عندما تريد سياقًا مشروطًا، حيث تحلّ واجهة مستخدم الإكمال التلقائي محلّ واجهة مستخدم التطبيق مؤقتًا إلى أن يحدّد المستخدم اختياره. توفّر فئة GMSAutocompleteViewController هذه الوظيفة. عندما يختار المستخدم مكانًا، يتلقّى تطبيقك معاودة الاتصال.

لإضافة عنصر تحكّم في وضع ملء الشاشة إلى تطبيقك:

  1. أنشِئ عنصر واجهة مستخدم في تطبيقك الرئيسي لتشغيل عنصر التحكّم "الإكمال التلقائي" في واجهة المستخدم، على سبيل المثال، معالِج اللمس على UIButton.
  2. نفِّذ بروتوكول GMSAutocompleteViewControllerDelegate في وحدة التحكم في العرض الرئيسية.
  3. يمكنك إنشاء نسخة افتراضية من GMSAutocompleteViewController وتخصيص وحدة التحكّم في الملف الشخصي الرئيسي كموقع إلكتروني مفوَّض.
  4. أنشئ GMSPlaceField لتحديد أنواع بيانات الأماكن المطلوب عرضها.
  5. أضِف GMSAutocompleteFilter لحصر طلب البحث بنوع مكان معيّن.
  6. اعرض GMSAutocompleteViewController باستخدام [self presentViewController...].
  7. التعامل مع اختيار المستخدم في طريقة التفويض didAutocompleteWithPlace
  8. ويمكنك تجاهل وحدة التحكّم في طرق التفويض didAutocompleteWithPlace وdidFailAutocompleteWithError وwasCancelled.

يوضح المثال التالي إحدى الطرق الممكنة لتشغيل GMSAutocompleteViewController استجابةً للمستخدِم الذي ينقر على أحد الأزرار.

Swift

import UIKit
import GooglePlaces

class ViewController: UIViewController {

  override func viewDidLoad() {
    makeButton()
  }

  // Present the Autocomplete view controller when the button is pressed.
  @objc func autocompleteClicked(_ sender: UIButton) {
    let autocompleteController = GMSAutocompleteViewController()
    autocompleteController.delegate = self

    // Specify the place data types to return.
    let fields: GMSPlaceField = GMSPlaceField(rawValue: UInt(GMSPlaceField.name.rawValue) |
      UInt(GMSPlaceField.placeID.rawValue))!
    autocompleteController.placeFields = fields

    // Specify a filter.
    let filter = GMSAutocompleteFilter()
    filter.types = [.address]
    autocompleteController.autocompleteFilter = filter

    // Display the autocomplete view controller.
    present(autocompleteController, animated: true, completion: nil)
  }

  // Add a button to the view.
  func makeButton() {
    let btnLaunchAc = UIButton(frame: CGRect(x: 5, y: 150, width: 300, height: 35))
    btnLaunchAc.backgroundColor = .blue
    btnLaunchAc.setTitle("Launch autocomplete", for: .normal)
    btnLaunchAc.addTarget(self, action: #selector(autocompleteClicked), for: .touchUpInside)
    self.view.addSubview(btnLaunchAc)
  }

}

extension ViewController: GMSAutocompleteViewControllerDelegate {

  // Handle the user's selection.
  func viewController(_ viewController: GMSAutocompleteViewController, didAutocompleteWith place: GMSPlace) {
    print("Place name: \(place.name)")
    print("Place ID: \(place.placeID)")
    print("Place attributions: \(place.attributions)")
    dismiss(animated: true, completion: nil)
  }

  func viewController(_ viewController: GMSAutocompleteViewController, didFailAutocompleteWithError error: Error) {
    // TODO: handle the error.
    print("Error: ", error.localizedDescription)
  }

  // User canceled the operation.
  func wasCancelled(_ viewController: GMSAutocompleteViewController) {
    dismiss(animated: true, completion: nil)
  }

  // Turn the network activity indicator on and off again.
  func didRequestAutocompletePredictions(_ viewController: GMSAutocompleteViewController) {
    UIApplication.shared.isNetworkActivityIndicatorVisible = true
  }

  func didUpdateAutocompletePredictions(_ viewController: GMSAutocompleteViewController) {
    UIApplication.shared.isNetworkActivityIndicatorVisible = false
  }

}

Objective-C

#import "ViewController.h"
@import GooglePlaces;

@interface ViewController () <GMSAutocompleteViewControllerDelegate>

@end

@implementation ViewController {
  GMSAutocompleteFilter *_filter;
}

- (void)viewDidLoad {
  [super viewDidLoad];
  [self makeButton];
}

  // Present the autocomplete view controller when the button is pressed.
- (void)autocompleteClicked {
  GMSAutocompleteViewController *acController = [[GMSAutocompleteViewController alloc] init];
  acController.delegate = self;

  // Specify the place data types to return.
  GMSPlaceField fields = (GMSPlaceFieldName | GMSPlaceFieldPlaceID);
  acController.placeFields = fields;

  // Specify a filter.
  _filter = [[GMSAutocompleteFilter alloc] init];
  _filter.types = @[ kGMSPlaceTypeBank ];
  acController.autocompleteFilter = _filter;

  // Display the autocomplete view controller.
  [self presentViewController:acController animated:YES completion:nil];
}

  // Add a button to the view.
- (void)makeButton{
  UIButton *btnLaunchAc = [UIButton buttonWithType:UIButtonTypeCustom];
  [btnLaunchAc addTarget:self
             action:NSSelectorFromString(@"autocompleteClicked") forControlEvents:UIControlEventTouchUpInside];
  [btnLaunchAc setTitle:@"Launch autocomplete" forState:UIControlStateNormal];
  btnLaunchAc.frame = CGRectMake(5.0, 150.0, 300.0, 35.0);
  btnLaunchAc.backgroundColor = [UIColor blueColor];
  [self.view addSubview:btnLaunchAc];
}

  // Handle the user's selection.
- (void)viewController:(GMSAutocompleteViewController *)viewController
didAutocompleteWithPlace:(GMSPlace *)place {
  [self dismissViewControllerAnimated:YES completion:nil];
  // Do something with the selected place.
  NSLog(@"Place name %@", place.name);
  NSLog(@"Place ID %@", place.placeID);
  NSLog(@"Place attributions %@", place.attributions.string);
}

- (void)viewController:(GMSAutocompleteViewController *)viewController
didFailAutocompleteWithError:(NSError *)error {
  [self dismissViewControllerAnimated:YES completion:nil];
  // TODO: handle the error.
  NSLog(@"Error: %@", [error description]);
}

  // User canceled the operation.
- (void)wasCancelled:(GMSAutocompleteViewController *)viewController {
  [self dismissViewControllerAnimated:YES completion:nil];
}

  // Turn the network activity indicator on and off again.
- (void)didRequestAutocompletePredictions:(GMSAutocompleteViewController *)viewController {
  [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}

- (void)didUpdateAutocompletePredictions:(GMSAutocompleteViewController *)viewController {
  [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}

@end

إضافة وحدة التحكم بالنتائج

يمكنك استخدام وحدة تحكّم بالنتائج إذا أردت التحكّم بشكل أكبر في واجهة مستخدم إدخال النص. تعمل وحدة التحكم في النتائج ديناميكيًا على تبديل ظهور قائمة النتائج بناءً على تركيز واجهة المستخدم للإدخال.

لإضافة وحدة تحكّم بالنتائج إلى تطبيقك، اتّبِع الخطوات التالية:

  1. إنشاء GMSAutocompleteResultsViewController
  2. نفِّذ بروتوكول GMSAutocompleteResultsViewControllerDelegate في وحدة التحكم في العرض الرئيسي، وخصِّص وحدة التحكّم في طريقة العرض الرئيسية كسمة التفويض.
  3. إنشاء كائن UISearchController، مع تمرير GMSAutocompleteResultsViewController كوسيطة وحدة التحكم في النتائج.
  4. اضبط السمة GMSAutocompleteResultsViewController على أنّها السمة searchResultsUpdater في UISearchController.
  5. أضِف searchBar الخاص بـ UISearchController إلى واجهة المستخدم في تطبيقك.
  6. التعامل مع اختيار المستخدم في طريقة التفويض didAutocompleteWithPlace

هناك عدة طرق لوضع شريط البحث الخاص بـ UISearchController في واجهة المستخدم الخاصة بتطبيقك:

إضافة شريط بحث إلى شريط التنقّل

يوضّح مثال الرمز التالي إضافة وحدة تحكّم بالنتائج وإضافة searchBar إلى شريط التنقّل والتعامل مع اختيار المستخدم:

Swift

class ViewController: UIViewController {

  var resultsViewController: GMSAutocompleteResultsViewController?
  var searchController: UISearchController?
  var resultView: UITextView?

  override func viewDidLoad() {
    super.viewDidLoad()

    resultsViewController = GMSAutocompleteResultsViewController()
    resultsViewController?.delegate = self

    searchController = UISearchController(searchResultsController: resultsViewController)
    searchController?.searchResultsUpdater = resultsViewController

    // Put the search bar in the navigation bar.
    searchController?.searchBar.sizeToFit()
    navigationItem.titleView = searchController?.searchBar

    // When UISearchController presents the results view, present it in
    // this view controller, not one further up the chain.
    definesPresentationContext = true

    // Prevent the navigation bar from being hidden when searching.
    searchController?.hidesNavigationBarDuringPresentation = false
  }
}

// Handle the user's selection.
extension ViewController: GMSAutocompleteResultsViewControllerDelegate {
  func resultsController(_ resultsController: GMSAutocompleteResultsViewController,
                         didAutocompleteWith place: GMSPlace) {
    searchController?.isActive = false
    // Do something with the selected place.
    print("Place name: \(place.name)")
    print("Place address: \(place.formattedAddress)")
    print("Place attributions: \(place.attributions)")
  }

  func resultsController(_ resultsController: GMSAutocompleteResultsViewController,
                         didFailAutocompleteWithError error: Error){
    // TODO: handle the error.
    print("Error: ", error.localizedDescription)
  }

  // Turn the network activity indicator on and off again.
  func didRequestAutocompletePredictions(_ viewController: GMSAutocompleteViewController) {
    UIApplication.shared.isNetworkActivityIndicatorVisible = true
  }

  func didUpdateAutocompletePredictions(_ viewController: GMSAutocompleteViewController) {
    UIApplication.shared.isNetworkActivityIndicatorVisible = false
  }
}

Objective-C

- (void)viewDidLoad {
  _resultsViewController = [[GMSAutocompleteResultsViewController alloc] init];
  _resultsViewController.delegate = self;

  _searchController = [[UISearchController alloc]
                       initWithSearchResultsController:_resultsViewController];
  _searchController.searchResultsUpdater = _resultsViewController;

  // Put the search bar in the navigation bar.
  [_searchController.searchBar sizeToFit];
  self.navigationItem.titleView = _searchController.searchBar;

  // When UISearchController presents the results view, present it in
  // this view controller, not one further up the chain.
  self.definesPresentationContext = YES;

  // Prevent the navigation bar from being hidden when searching.
  _searchController.hidesNavigationBarDuringPresentation = NO;
}

// Handle the user's selection.
- (void)resultsController:(GMSAutocompleteResultsViewController *)resultsController
  didAutocompleteWithPlace:(GMSPlace *)place {
    _searchController.active = NO;
    // Do something with the selected place.
    NSLog(@"Place name %@", place.name);
    NSLog(@"Place address %@", place.formattedAddress);
    NSLog(@"Place attributions %@", place.attributions.string);
}

- (void)resultsController:(GMSAutocompleteResultsViewController *)resultsController
didFailAutocompleteWithError:(NSError *)error {
  [self dismissViewControllerAnimated:YES completion:nil];
  // TODO: handle the error.
  NSLog(@"Error: %@", [error description]);
}

// Turn the network activity indicator on and off again.
- (void)didRequestAutocompletePredictionsForResultsController:
    (GMSAutocompleteResultsViewController *)resultsController {
  [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}

- (void)didUpdateAutocompletePredictionsForResultsController:
    (GMSAutocompleteResultsViewController *)resultsController {
  [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}

إضافة شريط بحث إلى أعلى طريقة عرض

يوضّح مثال الرمز التالي إضافة searchBar إلى أعلى طريقة عرض.

Swift

import UIKit
import GooglePlaces

class ViewController: UIViewController {

  var resultsViewController: GMSAutocompleteResultsViewController?
  var searchController: UISearchController?
  var resultView: UITextView?

  override func viewDidLoad() {
    super.viewDidLoad()

    resultsViewController = GMSAutocompleteResultsViewController()
    resultsViewController?.delegate = self

    searchController = UISearchController(searchResultsController: resultsViewController)
    searchController?.searchResultsUpdater = resultsViewController

    let subView = UIView(frame: CGRect(x: 0, y: 65.0, width: 350.0, height: 45.0))

    subView.addSubview((searchController?.searchBar)!)
    view.addSubview(subView)
    searchController?.searchBar.sizeToFit()
    searchController?.hidesNavigationBarDuringPresentation = false

    // When UISearchController presents the results view, present it in
    // this view controller, not one further up the chain.
    definesPresentationContext = true
  }
}

// Handle the user's selection.
extension ViewController: GMSAutocompleteResultsViewControllerDelegate {
  func resultsController(_ resultsController: GMSAutocompleteResultsViewController,
                         didAutocompleteWith place: GMSPlace) {
    searchController?.isActive = false
    // Do something with the selected place.
    print("Place name: \(place.name)")
    print("Place address: \(place.formattedAddress)")
    print("Place attributions: \(place.attributions)")
  }

  func resultsController(_ resultsController: GMSAutocompleteResultsViewController,
                         didFailAutocompleteWithError error: Error){
    // TODO: handle the error.
    print("Error: ", error.localizedDescription)
  }

  // Turn the network activity indicator on and off again.
  func didRequestAutocompletePredictions(forResultsController resultsController: GMSAutocompleteResultsViewController) {
    UIApplication.shared.isNetworkActivityIndicatorVisible = true
  }

  func didUpdateAutocompletePredictions(forResultsController resultsController: GMSAutocompleteResultsViewController) {
    UIApplication.shared.isNetworkActivityIndicatorVisible = false
  }
}

Objective-C

- (void)viewDidLoad {
    [super viewDidLoad];

    _resultsViewController = [[GMSAutocompleteResultsViewController alloc] init];
    _resultsViewController.delegate = self;

    _searchController = [[UISearchController alloc]
                             initWithSearchResultsController:_resultsViewController];
    _searchController.searchResultsUpdater = _resultsViewController;

    UIView *subView = [[UIView alloc] initWithFrame:CGRectMake(0, 65.0, 250, 50)];

    [subView addSubview:_searchController.searchBar];
    [_searchController.searchBar sizeToFit];
    [self.view addSubview:subView];

    // When UISearchController presents the results view, present it in
    // this view controller, not one further up the chain.
    self.definesPresentationContext = YES;
}

// Handle the user's selection.
- (void)resultsController:(GMSAutocompleteResultsViewController *)resultsController
didAutocompleteWithPlace:(GMSPlace *)place {
  [self dismissViewControllerAnimated:YES completion:nil];
  // Do something with the selected place.
  NSLog(@"Place name %@", place.name);
  NSLog(@"Place address %@", place.formattedAddress);
  NSLog(@"Place attributions %@", place.attributions.string);
}

- (void)resultsController:(GMSAutocompleteResultsViewController *)resultsController
didFailAutocompleteWithError:(NSError *)error {
  [self dismissViewControllerAnimated:YES completion:nil];
  // TODO: handle the error.
  NSLog(@"Error: %@", [error description]);
}

// Turn the network activity indicator on and off again.
- (void)didRequestAutocompletePredictionsForResultsController:
    (GMSAutocompleteResultsViewController *)resultsController {
  [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}

- (void)didUpdateAutocompletePredictionsForResultsController:
    (GMSAutocompleteResultsViewController *)resultsController {
  [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}

يُخفي UISearchController شريط التنقل تلقائيًا عند مشاركة العرض (يمكن إيقاف هذا). في الحالات التي يكون فيها شريط التنقّل مرئيًا ومعتمًا، لا يضبط UISearchController الموضع بشكل صحيح.

يمكنك استخدام الرمز التالي كحل بديل:

Swift

navigationController?.navigationBar.translucent = false
searchController?.hidesNavigationBarDuringPresentation = false

// This makes the view area include the nav bar even though it is opaque.
// Adjust the view placement down.
self.extendedLayoutIncludesOpaqueBars = true
self.edgesForExtendedLayout = .top

Objective-C

self.navigationController.navigationBar.translucent = NO;
_searchController.hidesNavigationBarDuringPresentation = NO;

// This makes the view area include the nav bar even though it is opaque.
// Adjust the view placement down.
self.extendedLayoutIncludesOpaqueBars = YES;
self.edgesForExtendedLayout = UIRectEdgeTop;

إضافة شريط بحث باستخدام نتائج منبثقة

يوضح مثال الرمز التالي وضع شريط بحث على الجانب الأيمن من شريط التنقل، وعرض النتائج في نافذة منبثقة.

Swift

import UIKit
import GooglePlaces

class ViewController: UIViewController {

  var resultsViewController: GMSAutocompleteResultsViewController?
  var searchController: UISearchController?
  var resultView: UITextView?

  override func viewDidLoad() {
    super.viewDidLoad()

    resultsViewController = GMSAutocompleteResultsViewController()
    resultsViewController?.delegate = self

    searchController = UISearchController(searchResultsController: resultsViewController)
    searchController?.searchResultsUpdater = resultsViewController

    // Add the search bar to the right of the nav bar,
    // use a popover to display the results.
    // Set an explicit size as we don't want to use the entire nav bar.
    searchController?.searchBar.frame = (CGRect(x: 0, y: 0, width: 250.0, height: 44.0))
    navigationItem.rightBarButtonItem = UIBarButtonItem(customView: (searchController?.searchBar)!)

    // When UISearchController presents the results view, present it in
    // this view controller, not one further up the chain.
    definesPresentationContext = true

    // Keep the navigation bar visible.
    searchController?.hidesNavigationBarDuringPresentation = false
    searchController?.modalPresentationStyle = .popover
  }
}
// Handle the user's selection.
extension ViewController: GMSAutocompleteResultsViewControllerDelegate {
  func resultsController(_ resultsController: GMSAutocompleteResultsViewController,
                         didAutocompleteWith place: GMSPlace) {
    searchController?.isActive = false
    // Do something with the selected place.
    print("Place name: \(place.name)")
    print("Place address: \(place.formattedAddress)")
    print("Place attributions: \(place.attributions)")
  }

  func resultsController(_ resultsController: GMSAutocompleteResultsViewController,
                         didFailAutocompleteWithError error: Error){
    // TODO: handle the error.
    print("Error: ", error.localizedDescription)
  }

  // Turn the network activity indicator on and off again.
  func didRequestAutocompletePredictions(forResultsController resultsController: GMSAutocompleteResultsViewController) {
    UIApplication.shared.isNetworkActivityIndicatorVisible = true
  }

  func didUpdateAutocompletePredictions(forResultsController resultsController: GMSAutocompleteResultsViewController) {
    UIApplication.shared.isNetworkActivityIndicatorVisible = false
  }
}

Objective-C

- (void)viewDidLoad {
  [super viewDidLoad];

  _resultsViewController = [[GMSAutocompleteResultsViewController alloc] init];
  _resultsViewController.delegate = self;

  _searchController = [[UISearchController alloc]
                           initWithSearchResultsController:_resultsViewController];
  _searchController.searchResultsUpdater = _resultsViewController;

  // Add the search bar to the right of the nav bar,
  // use a popover to display the results.
  // Set an explicit size as we don't want to use the entire nav bar.
  _searchController.searchBar.frame = CGRectMake(0, 0, 250.0f, 44.0f);
  self.navigationItem.rightBarButtonItem =
  [[UIBarButtonItem alloc] initWithCustomView:_searchController.searchBar];

  // When UISearchController presents the results view, present it in
  // this view controller, not one further up the chain.
  self.definesPresentationContext = YES;

  // Keep the navigation bar visible.
  _searchController.hidesNavigationBarDuringPresentation = NO;

  _searchController.modalPresentationStyle = UIModalPresentationPopover;
}

// Handle the user's selection.
- (void)resultsController:(GMSAutocompleteResultsViewController *)resultsController
didAutocompleteWithPlace:(GMSPlace *)place {
  [self dismissViewControllerAnimated:YES completion:nil];
  NSLog(@"Place name %@", place.name);
  NSLog(@"Place address %@", place.formattedAddress);
  NSLog(@"Place attributions %@", place.attributions.string);
}

- (void)resultsController:(GMSAutocompleteResultsViewController *)resultsController
didFailAutocompleteWithError:(NSError *)error {
  [self dismissViewControllerAnimated:YES completion:nil];
  // TODO: handle the error.
  NSLog(@"Error: %@", [error description]);
}

// Turn the network activity indicator on and off again.
- (void)didRequestAutocompletePredictionsForResultsController:
    (GMSAutocompleteResultsViewController *)resultsController {
  [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}

- (void)didUpdateAutocompletePredictionsForResultsController:
    (GMSAutocompleteResultsViewController *)resultsController {
  [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}

استخدام مصدر بيانات جدول

إذا كان تطبيقك يتضمّن واجهة مستخدم مخصّصة للبحث النصي، يمكنك استخدام الفئة GMSAutocompleteTableDataSource لعرض النتائج في جدول عرض النتائج على وحدة التحكّم في طريقة العرض.

لاستخدام GMSAutocompleteTableDataSource كمصدر البيانات وتفويض UITableView في وحدة التحكم في الملف الشخصي:

  1. نفِّذ البروتوكولَين GMSAutocompleteTableDataSourceDelegate وUISearchBarDelegate في وحدة التحكّم في العرض.
  2. أنشئ مثيل GMSAutocompleteTableDataSource وخصِّص وحدة التحكّم في الملف الشخصي لتكون السمة المفوَّضة.
  3. اضبط GMSAutocompleteTableDataSource كمصدر البيانات وخصائص التفويض للمثيل UITableView في وحدة التحكّم في الملف الشخصي.
  4. في معالِج إدخال نص البحث، يمكنك استدعاء sourceTextHasChanged على GMSAutocompleteTableDataSource.
  5. التعامل مع اختيار المستخدم في طريقة التفويض didAutocompleteWithPlace
  6. يمكنك إغلاق وحدة التحكّم في طرق التفويض didAutocompleteWithPlace أو didFailAutocompleteWithError أو wasCancelled.

يوضّح مثال الرمز التالي استخدام الفئة GMSAutocompleteTableDataSource لعرض جدول UIViewController عند إضافة UISearchBar بشكل منفصل.

Swift

// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import GooglePlaces
import UIKit

class PlaceAutocompleteViewController: UIViewController {

  private var tableView: UITableView!
  private var tableDataSource: GMSAutocompleteTableDataSource!

  override func viewDidLoad() {
    super.viewDidLoad()

    let searchBar = UISearchBar(frame: CGRect(x: 0, y: 20, width: self.view.frame.size.width, height: 44.0))
    searchBar.delegate = self
    view.addSubview(searchBar)

    tableDataSource = GMSAutocompleteTableDataSource()
    tableDataSource.delegate = self

    tableView = UITableView(frame: CGRect(x: 0, y: 64, width: self.view.frame.size.width, height: self.view.frame.size.height - 44))
    tableView.delegate = tableDataSource
    tableView.dataSource = tableDataSource

    view.addSubview(tableView)
  }
}

extension PlaceAutocompleteViewController: UISearchBarDelegate {
  func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    // Update the GMSAutocompleteTableDataSource with the search text.
    tableDataSource.sourceTextHasChanged(searchText)
  }
}

extension PlaceAutocompleteViewController: GMSAutocompleteTableDataSourceDelegate {
  func didUpdateAutocompletePredictions(for tableDataSource: GMSAutocompleteTableDataSource) {
    // Turn the network activity indicator off.
    UIApplication.shared.isNetworkActivityIndicatorVisible = false
    // Reload table data.
    tableView.reloadData()
  }

  func didRequestAutocompletePredictions(for tableDataSource: GMSAutocompleteTableDataSource) {
    // Turn the network activity indicator on.
    UIApplication.shared.isNetworkActivityIndicatorVisible = true
    // Reload table data.
    tableView.reloadData()
  }

  func tableDataSource(_ tableDataSource: GMSAutocompleteTableDataSource, didAutocompleteWith place: GMSPlace) {
    // Do something with the selected place.
    print("Place name: \(place.name)")
    print("Place address: \(place.formattedAddress)")
    print("Place attributions: \(place.attributions)")
  }

  func tableDataSource(_ tableDataSource: GMSAutocompleteTableDataSource, didFailAutocompleteWithError error: Error) {
    // Handle the error.
    print("Error: \(error.localizedDescription)")
  }

  func tableDataSource(_ tableDataSource: GMSAutocompleteTableDataSource, didSelect prediction: GMSAutocompletePrediction) -> Bool {
    return true
  }
}

      

Objective-C

// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#import "PlaceAutocompleteViewController.h"
@import GooglePlaces;
@import UIKit;

@interface PlaceAutocompleteViewController () <GMSAutocompleteTableDataSourceDelegate, UISearchBarDelegate>

@end

@implementation PlaceAutocompleteViewController {
  UITableView *tableView;
  GMSAutocompleteTableDataSource *tableDataSource;
}

- (void)viewDidLoad {
  [super viewDidLoad];

  UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 20, self.view.frame.size.width, 44)];
  searchBar.delegate = self;

  [self.view addSubview:searchBar];

  tableDataSource = [[GMSAutocompleteTableDataSource alloc] init];
  tableDataSource.delegate = self;

  tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, self.view.frame.size.width, self.view.frame.size.height - 44)];
  tableView.delegate = tableDataSource;
  tableView.dataSource = tableDataSource;

  [self.view addSubview:tableView];
}

#pragma mark - GMSAutocompleteTableDataSourceDelegate

- (void)didUpdateAutocompletePredictionsForTableDataSource:(GMSAutocompleteTableDataSource *)tableDataSource {
  // Turn the network activity indicator off.
  UIApplication.sharedApplication.networkActivityIndicatorVisible = NO;

  // Reload table data.
  [tableView reloadData];
}

- (void)didRequestAutocompletePredictionsForTableDataSource:(GMSAutocompleteTableDataSource *)tableDataSource {
  // Turn the network activity indicator on.
  UIApplication.sharedApplication.networkActivityIndicatorVisible = YES;

  // Reload table data.
  [tableView reloadData];
}

- (void)tableDataSource:(GMSAutocompleteTableDataSource *)tableDataSource didAutocompleteWithPlace:(GMSPlace *)place {
  // Do something with the selected place.
  NSLog(@"Place name: %@", place.name);
  NSLog(@"Place address: %@", place.formattedAddress);
  NSLog(@"Place attributions: %@", place.attributions);
}

- (void)tableDataSource:(GMSAutocompleteTableDataSource *)tableDataSource didFailAutocompleteWithError:(NSError *)error {
  // Handle the error
  NSLog(@"Error %@", error.description);
}

- (BOOL)tableDataSource:(GMSAutocompleteTableDataSource *)tableDataSource didSelectPrediction:(GMSAutocompletePrediction *)prediction {
  return YES;
}

#pragma mark - UISearchBarDelegate

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
  // Update the GMSAutocompleteTableDataSource with the search text.
  [tableDataSource sourceTextHasChanged:searchText];
}

@end

      

تخصيص ألوان النص والخلفية

يمكنك ضبط ألوان جميع النصوص والخلفيات في عنصر التحكّم في ميزة "الإكمال التلقائي" في واجهة المستخدم، وذلك لجعل الأداة أكثر تناسبًا مع المظهر المرئي للتطبيق. هناك طريقتان لضبط ألوان عناصر التحكم في واجهة المستخدم:

  • باستخدام بروتوكول واجهة المستخدم (UIUI) في نظام التشغيل iOS، لضبط عناصر تحكم واجهة المستخدم ذات النمط العام كلما أمكن ذلك. تنطبق هذه الإعدادات على العديد من عناصر التحكم في واجهة المستخدم، وليس كلها.
  • من خلال استخدام طرق حزمة تطوير البرامج (SDK) في فئات التطبيقات المصغّرة لضبط السمات التي لا تتوافق مع بروتوكول واجهة المستخدم (UIUI).

سيستخدم تطبيقك عادةً مزيجًا من بروتوكول واجهة المستخدم (UIUI) وطرق حزمة تطوير البرامج (SDK). يوضّح المخطّط التالي العناصر التي يمكن تصميمها:

الإكمال التلقائي لألوان عناصر التحكّم في واجهة المستخدم

يسرد الجدول التالي جميع عناصر واجهة المستخدم، ويشير إلى كيفية تصميم كل عنصر (بروتوكول واجهة المستخدم أو طريقة SDK).

عنصر في واجهة المستخدم الطريقة إرشادات متعلّقة بالموضة
درجة لون شريط التنقل (الخلفية) بروتوكول UIالمظهر يمكنك الاتصال بـ setBarTintColor على الخادم الوكيل UINavigationBar.
درجة اللون الخفيف لشريط التنقل (علامة إقحام نص شريط البحث وزر الإلغاء) بروتوكول UIالمظهر يمكنك الاتصال بـ setTintColor على الخادم الوكيل UINavigationBar.
لون نص شريط البحث بروتوكول UIالمظهر ضبط NSForegroundColorAttributeName في searchBarTextAttributes
لون شريط البحث لا ينطبق إنّ شريط البحث شفاف وسيعرض كنسخة مظللة من "شريط التنقل".
لون نص العنصر النائب في شريط البحث (نص البحث التلقائي) بروتوكول UIالمظهر ضبط NSForegroundColorAttributeName في placeholderAttributes
النص الأساسي (ينطبق أيضًا على نص الرسالة والخطأ) طريقة حزمة تطوير البرامج (SDK) تواصل هاتفيًا مع "primaryTextColor".
تمييز النص الأساسي طريقة حزمة تطوير البرامج (SDK) تواصل هاتفيًا مع "primaryTextHighlightColor".
النص الثانوي طريقة حزمة تطوير البرامج (SDK) تواصل هاتفيًا مع "secondaryTextColor".
الخطأ ونص الرسالة طريقة حزمة تطوير البرامج (SDK) تواصل هاتفيًا مع "primaryTextColor".
خلفية خلية الجدول طريقة حزمة تطوير البرامج (SDK) تواصل هاتفيًا مع "tableCellBackgroundColor".
لون فاصل خلايا الجدول طريقة حزمة تطوير البرامج (SDK) تواصل هاتفيًا مع "tableCellSeparatorColor".
الزر "إعادة المحاولة" طريقة حزمة تطوير البرامج (SDK) تواصل هاتفيًا مع "tintColor".
مؤشر النشاط (مؤشر التقدم) بروتوكول UIالمظهر يمكنك الاتصال بـ setColor على الخادم الوكيل UIActivityIndicatorView.
شعار "مُشغَّل بواسطة Google"، صورة سحابة إلكترونية حزينة لا ينطبق ويتم اختيار الإصدار الأبيض أو الرمادي تلقائيًا استنادًا إلى تباين الخلفية.
رموز العدسة المكبّرة ورموز النص الواضحة في حقل نص "شريط البحث" لا ينطبق لإنشاء النمط، استبدل الصور الافتراضية بصور للون المطلوب.

استخدام بروتوكول UIيقتصر على

يمكنك استخدام بروتوكول واجهة المستخدم (UIUI) للحصول على الخادم الوكيل للمظهر في عنصر واجهة مستخدم محدّد، والذي يمكنك استخدامه بعد ذلك لضبط لون عنصر واجهة المستخدم. عند إجراء تعديل، تتأثر جميع مثيلات عنصر واجهة المستخدم المعين. يغيِّر المثال التالي على مستوى العالم لون نص فئات UITextField إلى اللون الأخضر عند تضمينها في UISearchBar:

[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil]
    setDefaultTextAttributes:@{NSForegroundColorAttributeName:[UIColor greenColor]}];

لمزيد من المعلومات حول تحديد قيم الألوان، راجِع مرجع فئة UIColor.

تعرض مقتطفات الرمز التالية جميع أوامر الخادم الوكيل التي تحتاج إلى استخدامها لتصميم كل شيء في عنصر تحكم واجهة المستخدم للإكمال التلقائي بملء الشاشة. أضف هذه التعليمة البرمجية إلى طريقة didFinishLaunchingWithOptions في Appdelegate.m:

// Define some colors.
UIColor *darkGray = [UIColor darkGrayColor];
UIColor *lightGray = [UIColor lightGrayColor];

// Navigation bar background.
[[UINavigationBar appearance] setBarTintColor:darkGray];
[[UINavigationBar appearance] setTintColor:lightGray];

// Color of typed text in the search bar.
NSDictionary *searchBarTextAttributes = @{
                                          NSForegroundColorAttributeName: lightGray,
                                          NSFontAttributeName : [UIFont systemFontOfSize:[UIFont systemFontSize]]
                                          };
[UITextField appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]]
    .defaultTextAttributes = searchBarTextAttributes;

// Color of the placeholder text in the search bar prior to text entry.
NSDictionary *placeholderAttributes = @{
                                        NSForegroundColorAttributeName: lightGray,
                                        NSFontAttributeName : [UIFont systemFontOfSize:[UIFont systemFontSize]]
                                        };

// Color of the default search text.
// NOTE: In a production scenario, "Search" would be a localized string.
NSAttributedString *attributedPlaceholder =
[[NSAttributedString alloc] initWithString:@"Search"
                                attributes:placeholderAttributes];
[UITextField appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]]
    .attributedPlaceholder = attributedPlaceholder;

// Color of the in-progress spinner.
[[UIActivityIndicatorView appearance] setColor:lightGray];

// To style the two image icons in the search bar (the magnifying glass
// icon and the 'clear text' icon), replace them with different images.
[[UISearchBar appearance] setImage:[UIImage imageNamed:@"custom_clear_x_high"]
                  forSearchBarIcon:UISearchBarIconClear
                            state:UIControlStateHighlighted];
[[UISearchBar appearance] setImage:[UIImage imageNamed:@"custom_clear_x"]
                  forSearchBarIcon:UISearchBarIconClear
                            state:UIControlStateNormal];
[[UISearchBar appearance] setImage:[UIImage imageNamed:@"custom_search"]
                    forSearchBarIcon:UISearchBarIconSearch
                            state:UIControlStateNormal];

// Color of selected table cells.
UIView *selectedBackgroundView = [[UIView alloc] init];
selectedBackgroundView.backgroundColor = [UIColor lightGrayColor];
[UITableViewCell appearanceWhenContainedIn:[GMSAutocompleteViewController class], nil]
    .selectedBackgroundView = selectedBackgroundView;

إعداد خصائص نمط التحكم في واجهة المستخدم

تشتمل مجموعة فرعية من عناصر التحكم في واجهة المستخدم على خصائص لا تتأثر ببروتوكول واجهة المستخدم، وبالتالي يجب تعيينها مباشرةً. يوضّح مثال الرمز التالي تعريف ألوان المقدمة والخلفية، وتطبيقها على عنصر تحكّم في واجهة المستخدم باسم acController. أضِف هذا الرمز إلى الطريقة onLaunchClicked في ViewController.m:

UIColor *darkGray = [UIColor darkGrayColor];
UIColor *lightGray = [UIColor lightGrayColor];

acController.secondaryTextColor = [UIColor colorWithWhite:1.0f alpha:0.5f];
acController.primaryTextColor = lightGray;
acController.primaryTextHighlightColor = [UIColor grayColor];
acController.tableCellBackgroundColor = darkGray;
acController.tableCellSeparatorColor = lightGray;
acController.tintColor = lightGray;

الحصول على توقعات الأماكن آليًا

يمكنك إنشاء واجهة مستخدم بحث مخصّصة كبديل لواجهة المستخدم التي يوفّرها تطبيق "الإكمال التلقائي" المصغّر. ولإجراء ذلك، يجب أن يتلقّى تطبيقك توقّعات بشأن الأماكن آليًا. يمكن لتطبيقك الحصول على قائمة بأسماء و/أو عناوين الأماكن المتوقّعة بإحدى الطرق التالية:

سيتم الاتصال بالرقم GMSPlacesClient findAutocompletePredictionsFromQuery:

للحصول على قائمة بأسماء و/أو عناوين الأماكن المتوقّعة، أودّ توضيح GMSPlacesClient أولاً، ثم استدعِ الطريقة GMSPlacesClient findAutocompletePredictionsFromQuery: باستخدام المَعلمات التالية:

  • سلسلة autocompleteQuery تحتوي على النص الذي كتبه المستخدم.
  • رمز GMSAutocompleteSessionToken، الذي يُستخدم لتحديد كل جلسة على حدة يجب أن يمرّر تطبيقك الرمز المميّز نفسه لكل طلب طلب إكمال تلقائي، ثم يمرّر هذا الرمز المميّز مع رقم تعريف المكان في المكالمة اللاحقة إلى fetchPlacefromPlaceID: لاسترداد تفاصيل المكان للمكان الذي اختاره المستخدم.
  • GMSAutocompleteFilter لإجراء ما يلي:
    • التحيز أو قصر النتائج على منطقة معينة.
    • حصر النتائج على نوع مكان محدّد.
    • عنصر GMSPlaceLocationBias/Restriction لانحياز النتائج إلى منطقة معيّنة تحدّدها حدود خطوط الطول والعرض
  • طريقة معاودة الاتصال للتعامل مع التوقعات التي تم عرضها.

تعرض أمثلة الرموز أدناه مكالمة هاتفية إلى findAutocompletePredictionsFromQuery:.

Swift

/**
 * Create a new session token. Be sure to use the same token for calling
 * findAutocompletePredictions, as well as the subsequent place details request.
 * This ensures that the user's query and selection are billed as a single session.
 */
let token = GMSAutocompleteSessionToken.init()

// Create a type filter.
let filter = GMSAutocompleteFilter()
filter.types = [.bank] 
filter.locationBias = GMSPlaceRectangularLocationOption( northEastBounds,
                                   southWestBounds);

placesClient?.findAutocompletePredictions(fromQuery: "cheesebu",

                                          filter: filter,
                                          sessionToken: token,
                                          callback: { (results, error) in
    if let error = error {
      print("Autocomplete error: \(error)")
      return
    }
    if let results = results {
      for result in results {
        print("Result \(result.attributedFullText) with placeID \(result.placeID)")
      }
    }
})

Objective-C

/**
 * Create a new session token. Be sure to use the same token for calling
 * findAutocompletePredictionsFromQuery:, as well as the subsequent place details request.
 * This ensures that the user's query and selection are billed as a single session.
 */
GMSAutocompleteSessionToken *token = [[GMSAutocompleteSessionToken alloc] init];

// Create a type filter.
GMSAutocompleteFilter *_filter = [[GMSAutocompleteFilter alloc] init];
_filter.types = @[ kGMSPlaceTypeBank ];

[_placesClient findAutocompletePredictionsFromQuery:@"cheesebu"
filter:_filter sessionToken:token callback:^(NSArray<GMSAutocompletePrediction *> * _Nullable results, NSError * _Nullable error) {
  if (error != nil) {
    NSLog(@"An error occurred %@", [error localizedDescription]);
    return;
  }
  if (results != nil) {
    for (GMSAutocompletePrediction *result in results) {
      NSLog(@"Result %@ with PlaceID %@", result.attributedFullText, result.placeID);
    }
  }
}];

تستدعي واجهة برمجة التطبيقات طريقة معاودة الاتصال المحدّدة، مع تمرير مصفوفة من كائنات GMSAutocompletePrediction.

يحتوي كل كائن GMSAutocompletePrediction على المعلومات التالية:

  • attributedFullText – النص الكامل لعبارة البحث المقترحة في شكل NSAttributedString على سبيل المثال، "دار أوبرا سيدني، سيدني، نيو ساوث ويلز، أستراليا". ولكل نطاق نصي يتطابق مع البيانات التي أدخلها المستخدم السمة kGMSAutocompleteMatchAttribute. يمكنك استخدام هذه السمة لتمييز النص المطابق في استعلام المستخدم، على سبيل المثال، كما هو موضح أدناه.
  • placeID – رقم تعريف المكان للمكان المتوقّع معرّف المكان هو معرّف نصي يُعرّف المكان بشكلٍ فريد. لمزيد من المعلومات عن أرقام تعريف الأماكن، اطّلِع على نظرة عامة على رقم تعريف المكان.
  • distanceMeters – المسافة المستقيمة من origin المحددة إلى الوجهة. إذا لم يتم ضبط السمة origin، لن يتم عرض قيمة المسافة.

يوضّح مثال الرمز التالي كيفية تمييز أجزاء النتيجة التي تطابق النص في طلب بحث المستخدم بالخط الغامق، باستخدام enumerateAttribute:

Swift

let regularFont = UIFont.systemFont(ofSize: UIFont.labelFontSize)
let boldFont = UIFont.boldSystemFont(ofSize: UIFont.labelFontSize)

let bolded = prediction.attributedFullText.mutableCopy() as! NSMutableAttributedString
bolded.enumerateAttribute(kGMSAutocompleteMatchAttribute, in: NSMakeRange(0, bolded.length), options: []) {
  (value, range: NSRange, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
    let font = (value == nil) ? regularFont : boldFont
    bolded.addAttribute(NSFontAttributeName, value: font, range: range)
}

label.attributedText = bolded
    

Objective-C

UIFont *regularFont = [UIFont systemFontOfSize:[UIFont labelFontSize]];
UIFont *boldFont = [UIFont boldSystemFontOfSize:[UIFont labelFontSize]];

NSMutableAttributedString *bolded = [prediction.attributedFullText mutableCopy];
[bolded enumerateAttribute:kGMSAutocompleteMatchAttribute
                   inRange:NSMakeRange(0, bolded.length)
                   options:0
                usingBlock:^(id value, NSRange range, BOOL *stop) {
                  UIFont *font = (value == nil) ? regularFont : boldFont;
                  [bolded addAttribute:NSFontAttributeName value:font range:range];
                }];

label.attributedText = bolded;
    

استخدام برنامج الجلب

إذا أردت إنشاء عنصر تحكّم خاص في ميزة الإكمال التلقائي من البداية، يمكنك استخدام GMSAutocompleteFetcher الذي يلهم الإجراء autocompleteQuery على GMSPlacesClient. يقيّد برنامج الجلب الطلبات، ويعرض فقط النتائج لأحدث نص بحث تم إدخاله. ولا يوفر أي عناصر في واجهة المستخدم.

لتنفيذ GMSAutocompleteFetcher، اتّبِع الخطوات التالية:

  1. تنفيذ بروتوكول GMSAutocompleteFetcherDelegate.
  2. أنشئ كائن GMSAutocompleteFetcher.
  3. يمكنك استدعاء الدالة sourceTextHasChanged في برنامج الجلب حسب أنواع المستخدمين.
  4. يمكنك التعامل مع التوقّعات والأخطاء باستخدام أسلوبَي البروتوكول didAutcompleteWithPredictions وdidFailAutocompleteWithError.

يوضح مثال الرمز التالي استخدام الجلب للحصول على إدخالات المستخدم وعرض تطابقات الأماكن في عرض النص. تم حذف وظائف تحديد مكان. يُستمَد FetcherSampleViewController من UIViewController في FetcherSampleViewController.h.

Swift

import UIKit
import GooglePlaces

class ViewController: UIViewController {

  var textField: UITextField?
  var resultText: UITextView?
  var fetcher: GMSAutocompleteFetcher?

  override func viewDidLoad() {
    super.viewDidLoad()

    view.backgroundColor = .white
    edgesForExtendedLayout = []

    // Set bounds to inner-west Sydney Australia.
    let neBoundsCorner = CLLocationCoordinate2D(latitude: -33.843366,
                                                longitude: 151.134002)
    let swBoundsCorner = CLLocationCoordinate2D(latitude: -33.875725,
                                                longitude: 151.200349)

    // Set up the autocomplete filter.
    let filter = GMSAutocompleteFilter()
    filter.locationRestriction = GMSPlaceRectangularLocationOption(neBoundsCorner, swBoundsCorner)

    // Create a new session token.
    let token: GMSAutocompleteSessionToken = GMSAutocompleteSessionToken.init()

    // Create the fetcher.
    fetcher = GMSAutocompleteFetcher(bounds: nil, filter: filter)
    fetcher?.delegate = self
    fetcher?.provide(token)

    textField = UITextField(frame: CGRect(x: 5.0, y: 10.0,
                                          width: view.bounds.size.width - 5.0,
                                          height: 64.0))
    textField?.autoresizingMask = .flexibleWidth
    textField?.addTarget(self, action: #selector(textFieldDidChange(textField:)),
                         for: .editingChanged)
    let placeholder = NSAttributedString(string: "Type a query...")

    textField?.attributedPlaceholder = placeholder

    resultText = UITextView(frame: CGRect(x: 0, y: 65.0,
                                          width: view.bounds.size.width,
                                          height: view.bounds.size.height - 65.0))
    resultText?.backgroundColor = UIColor(white: 0.95, alpha: 1.0)
    resultText?.text = "No Results"
    resultText?.isEditable = false

    self.view.addSubview(textField!)
    self.view.addSubview(resultText!)
  }

  @objc func textFieldDidChange(textField: UITextField) {
    fetcher?.sourceTextHasChanged(textField.text!)
  }

}

extension ViewController: GMSAutocompleteFetcherDelegate {
  func didAutocomplete(with predictions: [GMSAutocompletePrediction]) {
    let resultsStr = NSMutableString()
    for prediction in predictions {
      resultsStr.appendFormat("\n Primary text: %@\n", prediction.attributedPrimaryText)
      resultsStr.appendFormat("Place ID: %@\n", prediction.placeID)
    }

    resultText?.text = resultsStr as String
  }

  func didFailAutocompleteWithError(_ error: Error) {
    resultText?.text = error.localizedDescription
  }
}

Objective-C

#import "FetcherSampleViewController.h"
#import <GooglePlaces/GooglePlaces.h>
#import <GoogleMapsBase/GoogleMapsBase.h>

@interface FetcherSampleViewController () <GMSAutocompleteFetcherDelegate>

@end

@implementation FetcherSampleViewController {
  UITextField *_textField;
  UITextView *_resultText;
  GMSAutocompleteFetcher* _fetcher;
}

- (void)viewDidLoad {
  [super viewDidLoad];

  self.view.backgroundColor = [UIColor whiteColor];
  self.edgesForExtendedLayout = UIRectEdgeNone;

  // Set bounds to inner-west Sydney Australia.
  CLLocationCoordinate2D neBoundsCorner = CLLocationCoordinate2DMake(-33.843366, 151.134002);
  CLLocationCoordinate2D swBoundsCorner = CLLocationCoordinate2DMake(-33.875725, 151.200349);

  GMSAutocompleteFilter *autocompleteFilter = [[GMSAutocompleteFilter alloc] init];
  autocompleteFilter.locationRestriction =
        GMSPlaceRectangularLocationOption(neBoundsCorner, swBoundsCorner);

  // Create the fetcher.
  _fetcher = [[GMSAutocompleteFetcher alloc] initWithBounds:nil
                                                     filter:filter];
  _fetcher.delegate = self;

  // Set up the UITextField and UITextView.
  _textField = [[UITextField alloc] initWithFrame:CGRectMake(5.0f,
                                                             0,
                                                             self.view.bounds.size.width - 5.0f,
                                                             44.0f)];
  _textField.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  [_textField addTarget:self
                 action:@selector(textFieldDidChange:)
       forControlEvents:UIControlEventEditingChanged];
  _resultText =[[UITextView alloc] initWithFrame:CGRectMake(0,
                                                            45.0f,
                                                            self.view.bounds.size.width,
                                                            self.view.bounds.size.height - 45.0f)];
  _resultText.backgroundColor = [UIColor colorWithWhite:0.95f alpha:1.0f];
  _resultText.text = @"No Results";
  _resultText.editable = NO;
  [self.view addSubview:_textField];
  [self.view addSubview:_resultText];
}

- (void)textFieldDidChange:(UITextField *)textField {
  NSLog(@"%@", textField.text);
  [_fetcher sourceTextHasChanged:textField.text];
}

#pragma mark - GMSAutocompleteFetcherDelegate
- (void)didAutocompleteWithPredictions:(NSArray *)predictions {
  NSMutableString *resultsStr = [NSMutableString string];
  for (GMSAutocompletePrediction *prediction in predictions) {
      [resultsStr appendFormat:@"%@\n", [prediction.attributedPrimaryText string]];
  }
  _resultText.text = resultsStr;
}

- (void)didFailAutocompleteWithError:(NSError *)error {
  _resultText.text = [NSString stringWithFormat:@"%@", error.localizedDescription];
}

@end

الرموز المميزة للجلسة

تعمل الرموز المميزة للجلسة على تجميع مرحلتي طلب البحث والاختيار ضمن بحث المستخدم للإكمال التلقائي في جلسة منفصلة لأغراض الفوترة. تبدأ الجلسة عندما يبدأ المستخدم في كتابة استعلام، وتنتهي عند تحديد مكان. يمكن أن تحتوي كل جلسة على استعلامات متعددة، متبوعة بتحديد مكان واحد. بعد انتهاء الجلسة، لن يصبح الرمز المميز صالحًا، بل يجب أن ينشئ تطبيقك رمزًا مميزًا جديدًا لكل جلسة. ننصح باستخدام الرموز المميّزة للجلسة لجميع جلسات الإكمال التلقائي الآلي (عند استخدام وحدة التحكّم بملء الشاشة أو وحدة التحكّم بالنتائج، تتولّى واجهة برمجة التطبيقات هذا الإجراء تلقائيًا).

تستخدم حزمة تطوير برامج الأماكن لأجهزة iOS رمز GMSAutocompleteSessionToken لتحديد كل جلسة. يجب أن يجتاز تطبيقك رمزًا مميّزًا جديدًا للجلسة عند بدء كل جلسة جديدة، ثم يمرّر هذا الرمز المميّز نفسه مع رقم تعريف المكان في المكالمة اللاحقة إلى fetchPlacefromPlaceID: لاسترداد تفاصيل المكان للمكان الذي اختاره المستخدم.

مزيد من المعلومات حول الرموز المميّزة للجلسة

استخدِم الرمز التالي لإنشاء رمز مميّز جديد للجلسة:

let token: GMSAutocompleteSessionToken = GMSAutocompleteSessionToken.init()

حدود الاستخدام

عرض عمليات تحديد المصدر في تطبيقك

  • إذا كان تطبيقك يستخدم خدمة الإكمال التلقائي بشكل آلي، يجب أن تعرض واجهة المستخدم إما إحالة "تدعمه Google" أو تظهر ضمن خريطة تحمل علامة Google التجارية.
  • إذا كان تطبيقك يستخدم عنصر التحكّم "الإكمال التلقائي" في واجهة المستخدم، لا حاجة إلى اتّخاذ أي إجراء إضافي (يتم عرض عملية تحديد المصدر المطلوبة تلقائيًا).
  • إذا تمكّنت من استرجاع معلومات إضافية عن المكان وعرضها بعد الحصول على مكان حسب رقم التعريف، عليك عرض سمات الجهات الخارجية أيضًا.

لمزيد من التفاصيل، راجع المستندات حول الإحالات.

التحكم في مؤشر نشاط الشبكة

للتحكم في مؤشر نشاط الشبكة في شريط حالة التطبيقات، يجب تنفيذ طرق التفويض الاختيارية المناسبة لفئة الإكمال التلقائي التي تستخدمها وتفعيل مؤشر الشبكة وإيقافه بنفسك.

  • بالنسبة إلى GMSAutocompleteViewController، يجب تنفيذ طريقتَي التفويض didRequestAutocompletePredictions: وdidUpdateAutocompletePredictions:.
  • بالنسبة إلى GMSAutocompleteResultsViewController، يجب تنفيذ طريقتَي التفويض didRequestAutocompletePredictionsForResultsController: وdidUpdateAutocompletePredictionsForResultsController:.
  • بالنسبة إلى GMSAutocompleteTableDataSource، يجب تنفيذ طريقتَي التفويض didRequestAutocompletePredictionsForTableDataSource: وdidUpdateAutocompletePredictionsForTableDataSource:.

من خلال تنفيذ هذه الطرق وضبط [UIApplication sharedApplication].networkActivityIndicatorVisible على YES وNO على التوالي، سيتطابق شريط الحالة مع واجهة مستخدم ميزة "الإكمال التلقائي" بشكل صحيح.

تقييد نتائج الإكمال التلقائي

يمكنك ضبط عنصر التحكّم في واجهة المستخدم الخاصة بميزة "الإكمال التلقائي" لحصر النتائج بمنطقة جغرافية معيّنة و/أو فلترة النتائج حسب نوع واحد أو أكثر من الأماكن أو إلى بلد معيّن أو بلدان معيّنة. لتقييد النتائج، يمكنك إجراء ما يلي:

  • إذا أردت تفضيل (انحياز) النتائج ضمن المنطقة المحددة، اضبط locationBias على GMSAutocompleteFilter (قد يستمر عرض بعض النتائج من خارج المنطقة المحددة). وإذا تم ضبط السمة locationRestriction أيضًا، سيتم تجاهل السمة locationBias.
  • لعرض (حصر) النتائج ضمن المنطقة المحددة فقط، اضبط locationRestriction على GMSAutocompleteFilter (وسيتم فقط عرض النتائج ضمن المنطقة المحدّدة).

    • ملاحظة: ينطبق هذا الشرط على مسارات كاملة فقط، وقد يتم عرض النتائج الاصطناعية الواقعة خارج الحدود المستطيلة استنادًا إلى مسار يتداخل مع القيود المفروضة على الموقع الجغرافي.
  • لعرض النتائج التي تتوافق مع نوع مكان معيّن فقط، يجب ضبط types على GMSAutocompleteFilter (على سبيل المثال، سيؤدي تحديد TypeFilter.ADDRESS إلى عرض الأداة للنتائج ذات العنوان الدقيق فقط).

  • لعرض النتائج فقط في ما يصل إلى خمسة بلدان محددة، اضبط countries على GMSAutocompleteFilter.

نتائج التحيز لمنطقة معينة

إذا أردت تفضيل (انحياز) النتائج ضمن المنطقة المحدّدة، اضبط locationBias على GMSAutocompleteFilter، كما هو موضّح هنا:

  northEast = CLLocationCoordinate2DMake(39.0, -95.0);
  southWest = CLLocationCoordinate2DMake(37.5, -100.0);
  GMSAutocompleteFilter *filter = [[GMSAutocompleteFilter alloc] init];
  filter.locationBias = GMSPlaceRectangularLocationOption(northEast, southWest);

حصر النتائج بمنطقة معيّنة

لعرض (حصر) النتائج فقط ضمن المنطقة المحدّدة، اضبط locationRestriction على GMSAutocompleteFilter، كما هو موضّح هنا:

  northEast = CLLocationCoordinate2DMake(39.0, -95.0);
  southWest = CLLocationCoordinate2DMake(37.5, -100.0);
  GMSAutocompleteFilter *filter = [[GMSAutocompleteFilter alloc] init];
  filter.locationRestriction = GMSPlaceRectangularLocationOption(northEast, southWest);

فلترة النتائج حسب البلد

لفلترة النتائج في ما يصل إلى خمسة بلدان محدَّدة، اضبط السمة countries على GMSAutocompleteFilter كما هو موضَّح هنا:

  GMSAutocompleteFilter *filter = [[GMSAutocompleteFilter alloc] init];
  filter.countries = @[ @"au", @"nz" ];

فلترة النتائج حسب نوع المكان أو نوع المجموعة

يمكنك حصر النتائج لتكون من نوع معيّن أو مجموعة أنواع معيّنة من خلال ضبط السمة types على GMSAutoCompleteFilter. استخدِم هذه السمة لتحديد الفلاتر المدرَجة في الجداول 1 و2 و3 في أنواع الأماكن. إذا لم يتم تحديد أي شيء، سيتم عرض جميع الأنواع.

لتحديد نوع أو نوع فلتر مجموعة:

  • استخدِم السمة types لتحديد ما يصل إلى خمس قيم type من الجدول 1 والجدول 2 المعروضة في أنواع الأماكن. يتم تعريف قيم الأنواع من خلال الثوابت في GMSPlaceType.

  • استخدِم السمة types لتحديد مجموعة أنواع من الجدول 3 المعروضة في أنواع الأماكن. يتم تحديد قيم مجموعة النوع من خلال الثوابت في GMSPlaceType.

    يُسمح بنوع واحد فقط من الجدول 3 في الطلب. إذا حددت قيمة من الجدول 3، فلا يمكنك تحديد قيمة من الجدول 1 أو الجدول 2. إذا قمت بذلك، فسيحدث خطأ.

على سبيل المثال، لعرض النتائج التي تتوافق مع نوع مكان محدّد فقط، اضبط types على GMSAutocompleteFilter. يوضح المثال التالي إعداد الفلتر لعرض النتائج ذات عنوان دقيق فقط:

  GMSAutocompleteFilter *filter = [[GMSAutocompleteFilter alloc] init];
  filter.types = @[ kGMSPlaceTypeAirport, kGMSPlaceTypeAmusementPark ];

تحسين الإكمال التلقائي للأماكن

يصف هذا القسم أفضل الممارسات لمساعدتك في الاستفادة إلى أقصى حدّ من خدمة "الإكمال التلقائي" للأماكن.

في ما يلي بعض الإرشادات العامة:

  • إنّ أسرع طريقة لتطوير واجهة مستخدم صالحة هي استخدام أداة الإكمال التلقائي الخاصة بـ "واجهة برمجة تطبيقات JavaScript للخرائط" أو أداة الإكمال التلقائي لـ "أماكن Google" أو حزمة تطوير برامج الأماكن لنظام التشغيل iOS عنصر التحكم في واجهة المستخدم للإكمال التلقائي.
  • تفهم حقول بيانات ميزة "الإكمال التلقائي" الأساسية للأماكن من البداية.
  • إنّ حقلَي انحياز الموقع الجغرافي وتقييد الموقع الجغرافي اختياريان، ولكن يمكن أن يكون لهما تأثير كبير في أداء ميزة الإكمال التلقائي.
  • يجب معالجة الأخطاء للتأكّد من تراجع أداء تطبيقك بشكل سلس في حال عرضت واجهة برمجة التطبيقات خطأً.
  • يجب التأكُّد من أنّ تطبيقك يعالج في حال عدم توفّر مجموعة محدَّدة وسيوفّر للمستخدمين طريقة للمتابعة.

أفضل الممارسات لتحسين التكلفة

التحسين الأساسي للتكاليف

لتحسين تكلفة استخدام خدمة "الإكمال التلقائي" للأماكن، استخدِم أقنعة الحقول في "تفاصيل المكان" و"أداة الإكمال التلقائي للأماكن" لعرض حقول بيانات الأماكن التي تحتاج إليها فقط.

التحسين المتقدم للتكلفة

يمكنك التنفيذ الآلي لميزة "الإكمال التلقائي" للأماكن للوصول إلى السعر لكل طلب وطلب نتائج واجهة برمجة التطبيقات Geocoding حول المكان المحدد بدلاً من "تفاصيل المكان". يكون التسعير لكل طلب المقترن بواجهة برمجة التطبيقات Geocoding API أكثر فعالية من حيث التكلفة من التسعير لكل جلسة (قائمة على الجلسة) في حال استيفاء الشرطَين التاليَين:

  • إذا كنت تحتاج فقط إلى خط العرض/الطول أو عنوان المكان الذي اختاره المستخدم، فإن واجهة برمجة تطبيقات Geocoding API توفر هذه المعلومات بتكلفة أقل من استدعاء "تفاصيل المكان".
  • إذا اختار المستخدمون عبارة بحث مقترحة للإكمال التلقائي في المتوسط بأربعة طلبات أو أقل من ذلك، قد يكون التسعير لكل طلب أكثر فعالية من حيث التكلفة من التسعير لكل جلسة.
للحصول على مساعدة في اختيار تنفيذ ميزة "الإكمال التلقائي" للأماكن التي تناسب احتياجاتك، اختَر علامة التبويب المقابلة لإجابتك على السؤال التالي.

هل يتطلب طلبك أي معلومات بخلاف العنوان وخط العرض/خط الطول للتوقّع المحدد؟

نعم، يجب توفير المزيد من التفاصيل.

استخدِم ميزة الإكمال التلقائي للأماكن المستنِدة إلى الجلسات مع تفاصيل المكان.
بما أنّ طلبك يتطلّب "تفاصيل المكان" مثل اسم المكان أو حالة النشاط التجاري أو ساعات العمل، يجب أن تستخدم ميزة "الإكمال التلقائي" للمكان رمزًا مميّزًا للجلسة (}{/1 أو مضمَّنًا في أدوات JavaScript أو Android أو iOS) بتكلفة إجمالية تبلغ 0.017 دولار أمريكي للجلسة بالإضافة إلى رموز التخزين التعريفية لبيانات الأماكن السارية على كل حقول بيانات الأماكن التي تطلبها.

تنفيذ الأداة
يتم دمج "إدارة الجلسات" تلقائيًا في التطبيقات المصغّرة JavaScript أو Android أو iOS. ويتضمن هذا كلاً من طلبات الإكمال التلقائي للأماكن وطلب "تفاصيل المكان" في التنبؤ المحدد. تأكّد من تحديد المَعلمة fields للتأكّد من أنّك تطلب فقط حقول بيانات الأماكن التي تحتاجها.

التنفيذ الآلي
استخدِم الرمز المميّز للجلسة مع طلبات الإكمال التلقائي للأماكن. عند طلب تفاصيل المكان المتعلّقة بالتوقّع المحدّد، يجب تضمين المَعلمات التالية:

  1. رقم تعريف المكان من ردّ الإكمال التلقائي للأماكن
  2. الرمز المميز للجلسة المستخدم في طلب الإكمال التلقائي للأماكن
  3. مَعلمة fields التي تحدِّد حقول بيانات الأماكن التي تحتاج إليها

لا، تحتاج فقط إلى العنوان والموقع الجغرافي

قد تكون واجهة برمجة التطبيقات Geocoding API خيارًا أكثر فعالية من حيث التكلفة من تفاصيل المكان لتطبيقك، وذلك بناءً على أداء استخدام ميزة الإكمال التلقائي للأماكن. تختلف كفاءة الإكمال التلقائي لكل تطبيق بناءً على الإدخالات التي يدخلها المستخدمون، والأماكن التي يتم استخدام التطبيق فيها، وما إذا كان قد تم تنفيذ أفضل ممارسات تحسين الأداء.

للإجابة عن السؤال التالي، حلِّل عدد الأحرف التي يكتبها المستخدم في المتوسط قبل اختيار إحدى عبارات البحث المقترحة من خلال ميزة "الإكمال التلقائي" للأماكن في تطبيقك.

هل يختار المستخدمون توقّعات ميزة "الإكمال التلقائي" للأماكن في أربعة طلبات أو أقل في المتوسط؟

نعم

يمكنك تنفيذ ميزة "الإكمال التلقائي" للأماكن تلقائيًا بدون الرموز المميّزة للجلسة واستدعاء واجهة برمجة التطبيقات Geocoding API على اقتراحات الأماكن المحدَّدة.
تقدِّم Geocoding API العناوين وإحداثيات خطوط الطول/العرض مقابل 0.005 دولار أمريكي لكل طلب. فإجراء أربعة طلبات من بيانات الإكمال التلقائي للأماكن - لكل طلب يكلف 0.01132 دولار أمريكي (أو ما يعادله بالعملة المحلية)، وبالتالي فإن التكلفة الإجمالية لأربعة طلبات بالإضافة إلى طلب استدعاء Geocoding API حول توقّع المكان المحدد ستكون 0.01632 دولار أمريكي (أو ما يعادله بالعملة المحلية)، وهو أقل من سعر الإكمال التلقائي لكل جلسة الذي يبلغ 0.017 دولار أمريكي (أو ما يعادله بالعملة المحلية) لكل جلسة.1

ننصحك باستخدام أفضل الممارسات المتعلقة بالأداء لمساعدة المستخدمين في الحصول على عبارات البحث المقترحة التي يبحثون عنها باستخدام عدد أقل من الأحرف.

لا

استخدِم ميزة الإكمال التلقائي للأماكن المستنِدة إلى الجلسات مع تفاصيل المكان.
بما أنّ متوسط عدد الطلبات التي تتوقع تقديمها قبل أن يختار المستخدم أحد توقعات الإكمال التلقائي لمكان يتجاوز تكلفة التسعير لكل جلسة، يجب أن تستخدم عملية تنفيذ ميزة "الإكمال التلقائي للأماكن" رمزًا مميّزًا للجلسة لكلّ من طلبات الإكمال التلقائي للأماكن وطلب تفاصيل المكان المرتبط بتكلفة إجمالية تبلغ 0.017 دولار أمريكي لكل جلسة.1

تنفيذ الأداة
يتم دمج "إدارة الجلسات" تلقائيًا في التطبيقات المصغّرة JavaScript أو Android أو iOS. ويتضمن هذا كلاً من طلبات الإكمال التلقائي للأماكن وطلب "تفاصيل المكان" في التنبؤ المحدد. تأكّد من تحديد المَعلمة fields لضمان أنّك تطلب حقول البيانات الأساسية فقط.

التنفيذ الآلي
استخدِم الرمز المميّز للجلسة مع طلبات الإكمال التلقائي للأماكن. عند طلب تفاصيل المكان المتعلّقة بالتوقّع المحدّد، يجب تضمين المَعلمات التالية:

  1. رقم تعريف المكان من ردّ الإكمال التلقائي للأماكن
  2. الرمز المميز للجلسة المستخدم في طلب الإكمال التلقائي للأماكن
  3. مَعلمة fields التي تحدِّد حقول البيانات الأساسية، مثل العنوان والشكل الهندسي

يمكنك تأخير طلبات الإكمال التلقائي للأماكن
يمكنك استخدام استراتيجيات مثل تأخير طلب الإكمال التلقائي للأماكن حتى يكتب المستخدم أول ثلاثة أو أربعة أحرف كي يقلِّل تطبيقك. على سبيل المثال، إذا كان تقديم طلبات الإكمال التلقائي من "الأماكن" لكل حرف بعد كتابة المستخدم للحرف الثالث يعني أنه إذا كتب المستخدم سبعة أحرف ثم اختار توقعًا تُجري له طلبًا واحدًا من أجل Geocoding API، ستكون التكلفة الإجمالية 0.01632 دولار أمريكي (أو ما يعادله بالعملة المحلية) (4 * $0.00283 لكل طلب + 0.005 دولار أمريكي (أو ما يعادله بالعملة المحلية) للترميز الجغرافي).1

إذا أدى تأخير الطلبات إلى خفض متوسط عدد الطلبات الآلية إلى أقل من أربعة، يمكنك اتّباع الإرشادات المتعلقة بتنفيذ الإكمال التلقائي للمكان باستخدام واجهة برمجة التطبيقات Geocoding API. يُرجى العلم أنّ المستخدم الذي قد يتوقّع ظهور توقعات مع كل ضغطة مفتاح جديدة قد ينظر إلى الطلبات المتأخّرة على أنّها وقت استجابة.

ننصحك باستخدام أفضل الممارسات المتعلقة بالأداء لمساعدة المستخدمين في الحصول على التوقّعات التي يبحثون عنها بأحرف أقل.


  1. التكاليف المدرجة هنا بالدولار الأمريكي. يُرجى الرجوع إلى صفحة الفوترة في "منصة خرائط Google" للاطّلاع على معلومات الأسعار الكاملة.

أفضل الممارسات المتعلقة بالأداء

توضّح الإرشادات التالية طُرق تحسين أداء ميزة "الإكمال التلقائي" للأماكن:

  • أضِف القيود المفروضة على البلدان وانحياز الموقع الجغرافي وتفضيل اللغة (للعمليات الآلية) إلى عملية تنفيذ ميزة "الإكمال التلقائي" للأماكن. لا حاجة إلى تفضيل اللغة مع التطبيقات المصغّرة، لأنّها تختار الإعدادات المفضّلة للّغة من متصفّح المستخدم أو جهازه الجوّال.
  • إذا كانت الإكمال التلقائي للأماكن مصحوبةً بخريطة، يمكنك انحياز الموقع حسب إطار عرض الخريطة.
  • في الحالات التي لا يختار فيها المستخدم أحد عبارات البحث المقترحة من خلال ميزة "الإكمال التلقائي"، وبشكل عام بسبب عدم ظهور أي من هذه التوقّعات في عنوان النتيجة المطلوب، يمكنك إعادة استخدام البيانات التي أدخلها المستخدم الأصلي لمحاولة الحصول على نتائج أكثر صلة:
    • إذا كنت تتوقّع أن يُدخل المستخدم معلومات العنوان فقط، أعِد استخدام الإدخال الأصلي في طلب Geocoding API.
    • إذا كنت تتوقّع أن يُدخل المستخدم طلبات بحث عن مكان معيّن حسب الاسم أو العنوان، استخدِم طلب البحث عن مكان. إذا كانت النتائج متوقعة فقط في منطقة معيّنة، استخدِم انحياز الموقع الجغرافي.
    تشمل السيناريوهات الأخرى عندما يكون من الأفضل الرجوع إلى Geocoding API ما يلي:
    • المستخدمون الذين يُدخلون عناوين مقرّات العمل الفرعية في بلدان لا تتوفّر فيها ميزة الإكمال التلقائي لعناوين الأماكن الفرعية، مثل التشيك وإستونيا وليتوانيا. على سبيل المثال، ينتج عن العنوان التشيكي "Stroupeovnického 3191/17, Praha" توقّع جزئي في ميزة "الإكمال التلقائي" من "الأماكن".
    • المستخدمون الذين يُدخلون عناوين مع بادئات أجزاء الطرق، مثل " 23-30 29th St, Queens" في مدينة نيويورك أو " 47-380 Kamehameha Hwy, Kaneohe" في جزيرة "كاواي" في "هاواي"

تحديد المشاكل وحلّها

على الرغم من إمكانية حدوث مجموعة متنوعة من الأخطاء، إلا أن معظم الأخطاء التي من المحتمل أن يواجهها تطبيقك عادةً ما تنتج عن أخطاء في الإعداد (على سبيل المثال، تم استخدام مفتاح واجهة برمجة تطبيقات خاطئ أو تم ضبط مفتاح واجهة برمجة التطبيقات بشكل غير صحيح) أو أخطاء في الحصة (تجاوز تطبيقك حصته). راجِع الحدود القصوى للاستخدام للحصول على مزيد من المعلومات حول الحصص.

يتم عرض الأخطاء التي تحدث عند استخدام عناصر تحكّم الإكمال التلقائي في طريقة didFailAutocompleteWithError() الخاصة ببروتوكولات التفويض المختلفة. يتم ضبط السمة code لكائن NSError المقدَّم على إحدى قيم التعداد GMSPlacesErrorCode.