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

اختَر النظام الأساسي: 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

      

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

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

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

سيستخدم تطبيقك عادةً مجموعة من بروتوكول واجهة المستخدم وطرق حزمة تطوير البرامج (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المظهر

يمكنك استخدام UIالمظهر للحصول على الخادم الوكيل للمظهر لعنصر واجهة مستخدم معيّن، والذي يمكنك استخدامه بعد ذلك لضبط لون عنصر واجهة المستخدم. عند إجراء تعديل، تتأثر جميع مثيلات عنصر واجهة مستخدم معين. على سبيل المثال، يغيِّر المثال التالي على مستوى العالم لون نص فئات 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;

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

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

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

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

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

تعرض أمثلة الرمز أدناه مكالمة للرقم 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" أداة الإكمال التلقائي أو حزمة تطوير البرامج (SDK) للأماكن المخصّصة لنظام التشغيل Android أو أداة الإكمال التلقائي أو حزمة تطوير البرامج للأماكن المخصّصة لنظام التشغيل iOS التحكم في الإكمال التلقائي لواجهة المستخدم
  • فهم حقول البيانات الأساسية الخاصة بالإكمال التلقائي للأماكن من البداية
  • يُعدّ حقلا "انحياز الموقع الجغرافي" و"حظر الموقع الجغرافي" اختياريًا، ولكن قد يكون لهما تأثير كبير في أداء الإكمال التلقائي.
  • استخدِم معالجة الأخطاء لضمان تراجع أداء تطبيقك بشكل آمن إذا ظهرت واجهة برمجة التطبيقات خطأ.
  • تأكَّد من أنّ تطبيقك يعالجه في حال عدم تحديد أي خيار، وأنّه يوفِّر للمستخدمين طريقة للمتابعة.

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

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

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

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

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

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

هل يتطلّب طلبك أي معلومات أخرى غير العنوان وخط العرض أو خط الطول لعبارة البحث المقترحة التي اخترتها؟

نعم، يجب تقديم تفاصيل إضافية.

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

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

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

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

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

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

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

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

نعم

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

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

لا

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

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

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

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

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

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

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


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

أفضل ممارسات الأداء

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

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

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

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

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