Автозаполнение мест (устаревшая версия)

Автозаполнение мест (устаревшая версия) возвращает подсказки мест в ответ на поисковые запросы пользователей. По мере ввода текста сервис автозаполнения предлагает варианты мест, например компаний, адресов, кодов Plus Code и объектов инфраструктуры.

Добавить автозаполнение в приложение можно следующими способами:

Добавление элемента управления пользовательского интерфейса с функцией автозаполнения

Элемент управления пользовательского интерфейса для автозаполнения – это диалоговое окно поиска со встроенной функцией автозаполнения. По мере того как пользователь вводит поисковый запрос, элемент управления предлагает список подсказок мест. Когда пользователь выбирает место, возвращается экземпляр 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 = [kGMSPlaceTypeCollectionAddress]
    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:@selector(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.
    1. Реализуйте протокол GMSAutocompleteResultsViewControllerDelegate в родительском контроллере представления и назначьте родительский контроллер представления в качестве свойства делегата.
  2. Создайте объект UISearchController, передав GMSAutocompleteResultsViewController в качестве аргумента контроллера результатов.
  3. Задайте GMSAutocompleteResultsViewController как свойство searchResultsUpdater для UISearchController.
  4. Добавьте searchBar для UISearchController в интерфейс приложения.
  5. Обработайте выбор пользователя в методе делегата 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.
    1. Обработайте выбор пользователя в методе делегата didAutocompleteWithPlace.
  5. Закройте контроллер в методах делегата 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

      

Настройка цветов текста и фона

Вы можете задать цвета для всего текста и фона в элементе управления пользовательского интерфейса с автозаполнением, чтобы виджет лучше соответствовал внешнему виду вашего приложения. Для настройки цвета элемента управления пользовательского интерфейса существуют два способа:

  • Используйте встроенный протокол UIAppearance для iOS, чтобы по возможности задавать глобальные стили для элементов управления пользовательского интерфейса. Эти настройки применяются ко многим, но не ко всем элементам управления пользовательского интерфейса.
  • Используйте методы SDK в классах виджетов, чтобы задать свойства, которые не поддерживаются протоколом UIAppearance.

Как правило, в приложении используется сочетание протокола UIAppearance и методов SDK. На приведенной ниже диаграмме показано, для каких элементов можно изменить стиль.

Цвета элементов управления пользовательского интерфейса автозаполнения

В таблице ниже перечислены все элементы интерфейса и указано, как следует настраивать стиль каждого из них (протокол UIAppearance или метод SDK).

Элемент интерфейса Метод Модные советы
Цвет панели навигации (фон) Протокол UIAppearance Вызов setBarTintColor на прокси-сервере UINavigationBar.
Цвет панели навигации (курсор в строке поиска и кнопка "Отмена") Протокол UIAppearance Вызов setTintColor на прокси-сервере UINavigationBar.
Цвет текста в строке поиска Протокол UIAppearance Задайте NSForegroundColorAttributeName в searchBarTextAttributes.
Цвет строки поиска Н/Д Строка поиска полупрозрачна и выглядит как затененная версия панели навигации.
Цвет текста-плейсхолдера в строке поиска (текст поиска по умолчанию) Протокол UIAppearance Задайте NSForegroundColorAttributeName в placeholderAttributes.
Основной текст (также применяется к тексту ошибок и сообщений) Метод SDK Позвоните в компанию "primaryTextColor".
Выделение основного текста Метод SDK Позвоните в компанию "primaryTextHighlightColor".
Дополнительный текст Метод SDK Позвоните в компанию "secondaryTextColor".
Ошибка и текст сообщения Метод SDK Позвоните в компанию "primaryTextColor".
Фон ячейки таблицы Метод SDK Позвоните в компанию "tableCellBackgroundColor".
Цвет разделителя ячеек таблицы Метод SDK Позвоните в компанию "tableCellSeparatorColor".
Кнопка "Повторить попытку" Метод SDK Позвоните в компанию "tintColor".
Индикатор активности (индикатор выполнения) Протокол UIAppearance Вызов setColor на прокси-сервере UIActivityIndicatorView.
Логотип "Технологии Google", изображение грустного облака Н/Д Белый или серый вариант выбирается автоматически в зависимости от контрастности фона.
Значки лупы и очистки текста в текстовом поле строки поиска Н/Д Чтобы изменить стиль, замените изображения по умолчанию на изображения нужного цвета.

Использование протокола UIAppearance

Вы можете использовать протокол UIAppearance, чтобы получить прокси-сервер внешнего вида для определенного элемента пользовательского интерфейса, который затем можно использовать для установки цвета элемента пользовательского интерфейса. При изменении элемента пользовательского интерфейса затрагиваются все его экземпляры. Например, в следующем примере цвет текста классов 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;

Настройка свойств стиля элементов управления пользовательского интерфейса

У некоторых элементов управления пользовательского интерфейса есть свойства, на которые не влияет протокол UIAppearance, поэтому их нужно задавать напрямую. В примере кода ниже показано, как определить цвета переднего плана и фона и применить их к экземпляру элемента управления пользовательского интерфейса с названием 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 = [kGMSPlaceTypeBank]
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);
    }
  }
}];

API вызывает указанный метод обратного вызова, передавая массив объектов 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>

@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

Токены сеансов

Токены сеансов группируют этапы запроса и выбора выполняемого пользователем поиска с функцией автозаполнения в отдельный сеанс для выставления счетов. Сеанс начинается в тот момент, когда пользователь начинает вводить запрос, а завершается тогда, когда он выбирает место. В каждом сеансе может быть несколько запросов, после которых следует выбор одного места. Когда сеанс завершается, токен перестает быть действительным. Ваше приложение должно создавать новый токен для каждого сеанса. Рекомендуем использовать токены сеансов для всех сеансов автозаполнения, выполняемых программно (при использовании контроллера полноэкранного режима или контроллера результатов API делает это автоматически).

Places SDK для 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 (например, если указать kGMSPlaceTypeCollectionAddress, виджет будет возвращать только результаты с точным адресом).

  • Чтобы получать результаты только по определенным странам (не более пяти), задайте параметр 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 ];

Оптимизация автозаполнения мест (устаревшая версия)

В этом разделе приведены рекомендации по эффективному использованию устаревшего сервиса автозаполнения мест.

Рассмотрим некоторые общие рекомендации.

Рекомендации по оптимизации затрат

Базовая оптимизация затрат

Для оптимизации затрат на сервис автозаполнения мест (Legacy) используйте маски полей в виджетах информации о местах (Legacy) и автозаполнения мест (Legacy), чтобы они возвращали только нужные вам поля данных автозаполнения мест (Legacy).

Дополнительная оптимизация затрат

Рассмотрите возможность программно реализовать сервис Place Autocomplete (Legacy), чтобы получить доступ к тарифу Autocomplete – Per Request и запрашивать результаты Geocoding API о выбранном месте вместо Place Details (Legacy). Тариф Per Request в сочетании Geocoding API будет выгоднее, чем тариф Per Session (на основе сеансов), если соблюдаются два следующих условия:

  • Если вам нужны только широта и долгота или адрес выбранного пользователем места, получить эту информацию с помощью Geocoding API дешевле, чем вызывать Place Details (Legacy).
  • Если пользователи выбирают подсказку автозаполнения мест в среднем из первых четырех запросов автозаполнения мест (устаревшее) или из меньшего числа, тариф Per Request может быть выгоднее, чем Per Session.
Чтобы выбрать реализацию автозаполнения мест (Legacy), которая будет наиболее выгодной для вашего приложения, найдите в таблице ниже строку, соответствующую потребностям вашего приложения.
Что нужно для подачи заявки Среднее количество запросов автозаполнения мест (Legacy), прежде чем пользователь выберет подсказку Рекомендуемые решения
Информация о месте, кроме адреса и местоположения, например название, статус компании или часы работы. Не ограничено Автозаполнение мест на основе сеансов (устаревшая версия) с информацией о местах (устаревшая версия)
Только адрес и широта и долгота выбранной подсказки Четыре или меньше Автозаполнение мест (устаревшее) с оплатой за запрос и Geocoding API
Только адрес и широта и долгота выбранной подсказки Больше четырех Автозаполнение мест на основе сеансов (устаревшая версия) для приложений, работающих только с адресами

Возможно, для вашего приложения Geocoding API будет более выгодным вариантом, чем Place Details (Legacy). Это зависит от того, насколько эффективно вы используете Place Autocomplete (Legacy). Эффективность функции автозаполнения мест (устаревшей) в каждом приложении зависит от того, какие запросы вводят пользователи, где используется приложение и реализованы ли рекомендации по оптимизации производительности.

Чтобы найти среднее количество запросов для таблицы, проанализируйте, сколько символов в среднем вводит пользователь, прежде чем выбирать подсказку автозаполнения мест (Legacy) в приложении.

Автозаполнение мест на основе сеансов (устаревшая версия) с информацией о местах (устаревшая версия)

Используйте сервис автозаполнения мест (устаревший) на основе сеансов совместно с информацией о местах (устаревшая версия).
Поскольку вашему приложению требуется информация о местах (устаревшая версия), например название места, статус компании или часы работы, в вашей реализации Place Autocomplete (устаревшая версия) должен использоваться токен сеанса (программно или встроенный в виджеты JavaScript, Android или iOS) за сеанс плюс применимые коды Places Data в зависимости от того, какие поля данных о местах вы запрашиваете.1

Реализация виджета
Функция автоматического управления сеансами встроена в виджеты для JavaScript, Android и iOS. В нее входят как запросы автозаполнения мест (Legacy), так и запрос информации о местах (Legacy) для выбранной подсказки. Обязательно укажите параметр fields, чтобы запрашивались только нужные поля данных автозаполнения мест (Legacy).

Программная реализация
Используйте токен сеанса с запросами Place Autocomplete (Legacy). При запросе информации о местах (Legacy) по выбранной подсказке укажите следующие параметры:

  1. идентификатор места из ответа автозаполнения мест (устаревшая версия)
  2. токен сеанса, использованный в запросе автозаполнения мест (устаревшая версия);
  3. Параметр fields, указывающий нужные поля данных автозаполнения мест (устаревшее).

Автозаполнение мест с оплатой за запрос (устаревшая версия) с Geocoding API

Реализуйте автозаполнение мест (Legacy) программно без токенов сеансов и вызывайте Geocoding API для выбранной подсказки места.
Geocoding API предоставляет адреса и координаты широты и долготы. Четыре запроса Autocomplete – Per Request вместе с вызовом Geocoding API о выбранной подсказке места стоят меньше, чем один сеанс автозаполнения мест (Legacy)1.

Вы можете применить рекомендации по оптимизации эффективности, чтобы помочь пользователям получать нужные подсказки, вводя минимальное количество символов.

Автозаполнение мест на основе сеансов (устаревшая версия) для приложений, работающих только с адресами

Используйте сервис автозаполнения мест (устаревший) на основе сеансов совместно с информацией о местах (устаревшая версия).
Поскольку среднее количество запросов, которые вы ожидаете сделать до того, как пользователь выберет подсказку автозаполнения мест (устаревшая версия), превышает стоимость тарифа за сеанс, в вашей реализации автозаполнения мест (устаревшая версия) должен использоваться токен сеанса как для запросов автозаполнения мест (устаревшая версия), так и для связанного запроса информации о местах (устаревшая версия) за сеанс. 1

Реализация виджета
Функция автоматического управления сеансами встроена в виджеты для JavaScript, Android и iOS. В нее входят как запросы автозаполнения мест (Legacy), так и запрос информации о местах (Legacy) для выбранной подсказки. Обязательно укажите параметр fields, чтобы запрашивались только нужные поля.

Программная реализация
Используйте токен сеанса с запросами Place Autocomplete (Legacy). Запрашивая у Place Details (Legacy) информацию о выбранной подсказке, указывайте следующие параметры:

  1. идентификатор места из ответа автозаполнения мест (устаревшая версия)
  2. токен сеанса, использованный в запросе автозаполнения мест (устаревшая версия);
  3. Параметр fields, указывающий поля данных Basic Data, например адрес и геометрические данные.

Рассмотрите возможность откладывать запросы автозаполнения мест (Legacy)
Вы можете попробовать различные стратегии, например откладывать запрос автозаполнения мест (Legacy), пока пользователь не введет первые три или четыре символа, чтобы ваше приложение совершало меньше запросов. Например, если вы отправляете запросы Place Autocomplete (Legacy) для каждого символа после того, как пользователь ввел третий символ, то, если пользователь введет семь символов и выберет подсказку, для которой вы отправите один запрос Geocoding API, общая стоимость будет равна стоимости четырех запросов Place Autocomplete (Legacy) Per Request и одного запроса Geocoding API1.

Если при откладывании запросов среднее число автоматизированных запросов станет меньше четырех, вы сможете эффективно использовать сервис автозаполнения мест (Legacy) с Geocoding API. Обратите внимание, что пользователь, ожидающий появления подсказок с каждым введенным символом, может принять откладывание запросов за задержку.

Вы можете применить рекомендации по оптимизации эффективности, чтобы помочь пользователям получать нужные подсказки, вводя меньше символов.

Рекомендации по повышению эффективности

В рекомендациях ниже описаны способы оптимизации производительности автозаполнения мест (Legacy):

  • Добавьте в свою реализацию Place Autocomplete (Legacy) ограничения по стране, предпочтение местоположений и (для программных реализаций) предпочитаемый язык. Предпочитаемый язык не нужен в случае виджетов, потому что для них язык определяется на основе языковых настроек браузера или мобильного устройства.
  • Если вместе с автозаполнением мест (Legacy) отображается карта, вы можете сделать предпочитаемым местоположением видимую область карты.
  • Если пользователь не выберет ни одну из подсказок автозаполнения мест (Legacy) – чаще всего такое бывает, если ни одна из них не соответствует искомому адресу, — вы можете повторно использовать изначально введенные пользователем данные, чтобы получить более подходящие результаты:
    • Если вы рассчитываете, что пользователь будет вводить только информацию об адресе, повторно используйте изначально введенные им данные в вызове Geocoding API.
    • Если пользователь скорее всего будет вводить запросы для определенного места по названию или адресу, используйте запрос информации о местах (устаревший). Если ожидается, что результаты будут из определенного региона, используйте предпочтение местоположений.
    К другим сценариям, при которых лучше вернуться к использованию Geocoding API, относятся следующие:
    • Пользователи вводят адреса, содержащие номер квартиры или офиса. Так, для адреса в Чехии "Stroupežnického 3191/17, Praha" автозаполнение мест (устаревшее) покажет частичную подсказку.
    • Пользователь вводит адрес с префиксом для ряда домов, например "23-30 29th St, Queens" в Нью-Йорке или "47-380 Kamehameha Hwy, Kaneohe" на острове Кауаи (Гавайи).

Привязка к местоположению

Настроить предпочтение результатов из определенной области с помощью параметров location и radius. Это указывает автозаполнению мест (Legacy) предпочитать результаты в пределах заданной области. однако более отдаленные точки также могут быть включены в ответ. С помощью параметра includedRegionCodes можно отфильтровать результаты, чтобы в них показывались только места в указанной стране.

Ограничение местоположений

Ограничить результаты определенной областью, передав параметр locationRestriction.

Вы также можете ограничить результаты регионом, заданным параметрами location и radius, добавив параметр strictbounds. В этом случае автозаполнение мест (устаревшее) будет возвращать результаты только из указанного региона.

Устранение неполадок

Хотя могут возникать самые разные ошибки, большинство из них обычно связано с конфигурацией (например, используется неправильный ключ API или ключ API настроен неправильно) или квотами (приложение превысило квоту). Подробную информацию о квотах можно найти в разделе Лимиты на использование.

Ошибки, возникающие при использовании элементов управления автозаполнением, возвращаются в методе didFailAutocompleteWithError() различных протоколов делегатов. Свойство code объекта NSError, переданного в функцию, принимает одно из значений перечисления GMSPlacesErrorCode.