Place Autocomplete (heredado)

Place Autocomplete (heredado) devuelve predicciones de lugares en respuesta a las búsquedas de los usuarios. A medida que el usuario escribe, el servicio de autocompletado devuelve sugerencias de lugares, como empresas, direcciones, Plus Codes y lugares de interés.

Puedes agregar el autocompletado a tu aplicación de las siguientes formas:

Agrega un control de la IU con la función de autocompletar

El control de la IU de la función de autocompletar es un diálogo de búsqueda con una funcionalidad de autocompletado integrada. A medida que el usuario ingresa términos de búsqueda, el control presenta una lista de lugares previstos para elegir. Cuando el usuario realiza una selección, se devuelve una instancia de GMSPlace, que tu app puede usar para obtener detalles sobre el lugar seleccionado.

Puedes agregar los controles de la IU con la función de autocompletar a tu app de las siguientes maneras:

Cómo agregar un control de pantalla completa

Usa el control de pantalla completa cuando quieras un contexto modal, en el que la IU de Autocomplete reemplace temporalmente la IU de tu app hasta que el usuario haya realizado su selección. La clase GMSAutocompleteViewController proporciona esta funcionalidad. Cuando el usuario selecciona un sitio, tu aplicación recibe un callback.

Para agregar el control de pantalla completa a tu aplicación:

  1. Crea un elemento de la IU en tu app principal para iniciar el control de la IU de autocompletar, por ejemplo, un controlador táctil en un UIButton.
  2. Implementa el protocolo GMSAutocompleteViewControllerDelegate en el controlador de vista parental.
  3. Crea una instancia de GMSAutocompleteViewController y asigna el controlador de vista superior como la propiedad del delegado.
  4. Crea un objeto GMSPlaceField para definir los tipos de datos de lugar que se devolverán.
  5. Agrega un GMSAutocompleteFilter para restringir la consulta a un tipo de lugar en particular.
  6. Presenta el GMSAutocompleteViewController con [self presentViewController...].
  7. Controla la selección del usuario en el método delegado didAutocompleteWithPlace.
  8. Descarta el controlador en los métodos delegados didAutocompleteWithPlace, didFailAutocompleteWithError y wasCancelled.

En el siguiente ejemplo, se muestra una posible forma de iniciar GMSAutocompleteViewController en respuesta al usuario que presiona un botón.

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

Agrega un controlador de resultados

Usa un controlador de resultados cuando desees un mayor control sobre la IU de entrada de texto. El controlador de resultados activa o desactiva de forma dinámica la visibilidad de la lista de resultados según el enfoque de la IU de entrada.

Para agregar un controlador de resultados a tu aplicación:

  1. Crea un GMSAutocompleteResultsViewController.
    1. Implementa el protocolo GMSAutocompleteResultsViewControllerDelegate en el controlador de vista parental y asígnalo como la propiedad del delegado.
  2. Crea un objeto UISearchController y pasa GMSAutocompleteResultsViewController como el argumento del controlador de resultados.
  3. Establece GMSAutocompleteResultsViewController como la propiedad searchResultsUpdater de UISearchController.
  4. Agrega el searchBar para el UISearchController a la IU de tu app.
  5. Controla la selección del usuario en el método delegado didAutocompleteWithPlace.

Existen varias formas de colocar la barra de búsqueda de un UISearchController en la IU de tu app:

Agrega una barra de búsqueda a la barra de navegación

En el siguiente ejemplo de código, se muestra cómo agregar un controlador de resultados, agregar la searchBar a la barra de navegación y controlar la selección del usuario:

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;
}

Agrega una barra de búsqueda en la parte superior de una vista

En el siguiente ejemplo de código, se muestra cómo agregar el searchBar a la parte superior de una vista.

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;
}

De forma predeterminada, UISearchController oculta la barra de navegación durante la presentación (esto se puede inhabilitar). En los casos en que la barra de navegación es visible y opaca, UISearchController no establece la posición correctamente.

Usa el siguiente código como solución:

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;

Agrega una barra de búsqueda con resultados emergentes

En el siguiente ejemplo de código, se muestra cómo colocar una barra de búsqueda en el lado derecho de la barra de navegación y mostrar los resultados en una ventana emergente.

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;
}

Usa una fuente de datos de tabla

Si tu app tiene una IU de texto de búsqueda personalizada, puedes usar la clase GMSAutocompleteTableDataSource para controlar la vista de tabla que muestra los resultados en el controlador de vista.

Para usar GMSAutocompleteTableDataSource como la fuente de datos y el delegado de UITableView en un controlador de vista, haz lo siguiente:

  1. Implementa los protocolos GMSAutocompleteTableDataSourceDelegate y UISearchBarDelegate en el controlador de vista.
  2. Crea una instancia de GMSAutocompleteTableDataSource y asigna el controlador de vista como la propiedad del delegado.
  3. Establece GMSAutocompleteTableDataSource como las propiedades de fuente de datos y delegado de la instancia de UITableView en el controlador de vista.
  4. En el controlador de la entrada de texto de búsqueda, llama a sourceTextHasChanged en GMSAutocompleteTableDataSource.
    1. Controla la selección del usuario en el método delegado didAutocompleteWithPlace.
  5. Descarta el controlador en los métodos delegados didAutocompleteWithPlace, didFailAutocompleteWithError y wasCancelled.

En el siguiente ejemplo de código, se muestra cómo usar la clase GMSAutocompleteTableDataSource para controlar la vista de tabla de un UIViewController cuando se agrega el UISearchBar por separado.

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

      

Personaliza el texto y el color de fondo

Puedes configurar los colores de todo el texto y los fondos en el control de la IU de Autocomplete para que el widget coincida con la apariencia visual de tu app de forma más precisa. Existen dos maneras de establecer los colores de los controles de la IU:

  • Usa el protocolo UIAppearance integrado de iOS para aplicar un diseño global a los controles de la IU siempre que sea posible. Estos parámetros de configuración se aplican a muchos, pero no a todos, los elementos de control de la IU.
  • Usa los métodos del SDK en las clases de widgets para establecer propiedades que no sean compatibles con el protocolo UIAppearance.

Por lo general, tu app usará una combinación del protocolo UIAppearance y los métodos del SDK. En el siguiente diagrama, se muestran los elementos cuyo estilo se puede personalizar:

Colores de los controles de la IU de Autocomplete

En la siguiente tabla, se enumeran todos los elementos de la IU y se indica cómo se debe aplicar el estilo a cada uno (protocolo UIAppearance o método del SDK).

Elemento de la IU Método Consejos sobre estilo
Tinte de la barra de navegación (fondo) Protocolo UIAppearance Llama a setBarTintColor en el proxy UINavigationBar.
Color de tono de la barra de navegación (cursor de texto de la barra de búsqueda y botón Cancelar) Protocolo UIAppearance Llama a setTintColor en el proxy UINavigationBar.
Color del texto de la barra de búsqueda Protocolo UIAppearance Establece NSForegroundColorAttributeName en searchBarTextAttributes.
Color de tono de la barra de búsqueda N/A La barra de búsqueda es traslúcida y se mostrará como una versión sombreada de la barra de navegación.
Color del texto de marcador de posición de la barra de búsqueda (texto de búsqueda predeterminado) Protocolo UIAppearance Establece NSForegroundColorAttributeName en placeholderAttributes.
Texto principal (también se aplica al texto de error y de mensaje) Método del SDK Llamar a primaryTextColor
Destacar texto principal Método del SDK Llamar a primaryTextHighlightColor
Texto secundario Método del SDK Llamar a secondaryTextColor
Texto de error y mensaje Método del SDK Llamar a primaryTextColor
Fondo de la celda de la tabla Método del SDK Llamar a tableCellBackgroundColor
Color del separador de celdas de la tabla Método del SDK Llamar a tableCellSeparatorColor
Botón "Reintentar" Método del SDK Llamar a tintColor
Indicador de actividad (control de número de progreso) Protocolo UIAppearance Llama a setColor en el proxy UIActivityIndicatorView.
Logotipo de "Powered by Google", imagen de una nube triste N/A La versión blanca o gris se selecciona automáticamente según el contraste del fondo.
Íconos de lupa y de borrar texto en el campo de texto de la barra de búsqueda N/A Para aplicar un estilo, reemplaza las imágenes predeterminadas por imágenes del color deseado.

Usa el protocolo UIAppearance

Puedes usar el protocolo UIAppearance para obtener el proxy de apariencia de un elemento de la IU determinado, que luego puedes usar para establecer el color del elemento de la IU. Cuando se realiza una modificación, se ven afectadas todas las instancias de un elemento de la IU determinado. Por ejemplo, en el siguiente ejemplo, se cambia de forma global el color del texto de las clases UITextField a verde cuando están contenidas en un UISearchBar:

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

Para obtener más información sobre cómo definir los valores de color, consulta la referencia de la clase UIColor.

En los siguientes fragmentos de código, se muestran todos los comandos de proxy que necesitas usar para aplicar diseño a todo el control de la IU de la función de autocompletado en pantalla completa. Agrega este código al método didFinishLaunchingWithOptions en 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;

Cómo configurar las propiedades de estilo de los controles de la IU

Un subconjunto de elementos de control de la IU tiene propiedades que no se ven afectadas por el protocolo UIAppearance y, por lo tanto, se deben configurar directamente. En el siguiente ejemplo de código, se muestra cómo definir los colores de primer plano y de fondo, y cómo aplicarlos a una instancia de control de la IU llamada acController. Agrega este código al método onLaunchClicked en 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;

Obtén predicciones de lugares de manera programática

Puedes crear una IU de búsqueda personalizada como alternativa a la IU que proporciona el widget de autocompletado. Para ello, tu app debe obtener predicciones de lugares de forma programática. Tu app puede obtener una lista de nombres o direcciones de lugares previstos de una de las siguientes maneras:

Llamando a GMSPlacesClient findAutocompletePredictionsFromQuery:

Para obtener una lista de nombres o direcciones de lugares previstos, primero crea una instancia de GMSPlacesClient y, luego, llama al método GMSPlacesClient findAutocompletePredictionsFromQuery: con los siguientes parámetros:

  • Es una cadena autocompleteQuery que contiene el texto que escribió el usuario.
  • Un GMSAutocompleteSessionToken, que se usa para identificar cada sesión individual. Tu app debe pasar el mismo token para cada llamada de solicitud de Place Autocomplete y, luego, pasar ese token, junto con un ID de lugar, en la llamada posterior a fetchPlacefromPlaceID: para recuperar los detalles del lugar que seleccionó el usuario.
  • A GMSAutocompleteFilter a:
    • Personaliza o restringe los resultados a una región específica.
    • Restringe los resultados a un tipo de lugar específico.
    • Es un objeto GMSPlaceLocationBias/Restriction que personaliza los resultados para un área específica determinada por límites de latitud y longitud.
  • Es un método de devolución de llamada para controlar las predicciones que se devuelven.

En los siguientes ejemplos de código, se muestra una llamada a 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);
    }
  }
}];

La API invoca el método de devolución de llamada especificado y pasa un array de objetos GMSAutocompletePrediction.

Cada objeto GMSAutocompletePrediction contiene la siguiente información:

  • attributedFullText: Es el texto completo de la predicción, en forma de NSAttributedString. Por ejemplo, "Ópera de Sídney, Sídney, Nueva Gales del Sur, Australia". Cada rango de texto que coincide con la entrada del usuario tiene un atributo, kGMSAutocompleteMatchAttribute. Puedes usar este atributo para destacar el texto coincidente en la consulta del usuario, por ejemplo, como se muestra a continuación.
  • placeID: Es el ID de lugar del lugar previsto. Un ID de lugar es un identificador textual que identifica de forma exclusiva un lugar. Para obtener más información sobre los IDs de lugar, consulta la descripción general de los IDs de lugar.
  • distanceMeters: Es la distancia en línea recta desde el origin especificado hasta el destino. Si no se establece la propiedad origin, no se devolverá ningún valor de distancia.

En el siguiente ejemplo de código, se muestra cómo destacar en negrita las partes del resultado que coinciden con el texto de la consulta del usuario, con 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;
    

Usa el recuperador

Si quieres crear tu propio control de autocompletado desde cero, puedes usar GMSAutocompleteFetcher, que unifica el método autocompleteQuery en GMSPlacesClient. El recuperador limita las solicitudes y solo devuelve los resultados del texto de búsqueda ingresado más recientemente. No proporciona elementos de la IU.

Para implementar GMSAutocompleteFetcher, sigue estos pasos:

  1. Implementa el protocolo GMSAutocompleteFetcherDelegate.
  2. Crea un objeto GMSAutocompleteFetcher.
  3. Llama a sourceTextHasChanged en el recuperador a medida que el usuario escribe.
  4. Controla las predicciones y los errores con los métodos de protocolo didAutcompleteWithPredictions y didFailAutocompleteWithError.

En el siguiente ejemplo de código, se muestra cómo usar el recuperador para tomar la entrada del usuario y mostrar las coincidencias de lugares en una vista de texto. Se omitió la funcionalidad para seleccionar un lugar. FetcherSampleViewController deriva de UIViewController en 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

Tokens de sesión

Los tokens de sesión agrupan las etapas de consulta y selección de la búsqueda con autocompletado de un usuario en una sesión discreta para realizar la facturación correspondiente. La sesión se inicia cuando el usuario comienza a escribir una consulta y termina cuando selecciona un lugar. Cada sesión puede tener varias búsquedas, seguidas de una selección de lugar. Una vez que finaliza la sesión, el token deja de ser válido. Tu app debe generar un token nuevo para cada sesión. Te recomendamos usar tokens de sesión para todas las sesiones de autocompletado programáticas (cuando usas el controlador de pantalla completa o el controlador de resultados, la API se encarga de esto automáticamente).

El SDK de Places para iOS usa un GMSAutocompleteSessionToken para identificar cada sesión. Tu app debe pasar un token de sesión nuevo cuando comienza cada sesión nueva y, luego, pasar ese mismo token, junto con un ID de lugar, en la llamada posterior a fetchPlacefromPlaceID: para recuperar los Place Details del lugar que seleccionó el usuario.

Obtén más información sobre los tokens de sesión.

Usa el siguiente código para generar un token de sesión nuevo:

let token: GMSAutocompleteSessionToken = GMSAutocompleteSessionToken.init()

Límites de uso

Cómo mostrar atribuciones en tu app

  • Si tu app usa el servicio de autocompletado de manera programática, tu IU debe mostrar una atribución "Con tecnología de Google" o aparecer dentro de un mapa con la marca de Google.
  • Si tu app usa el control de IU de Autocomplete, no se requiere ninguna acción adicional (la atribución requerida se muestra de forma predeterminada).
  • Si recuperas y muestras información adicional sobre un lugar después de obtenerlo por ID, también debes mostrar las atribuciones de terceros.

Para obtener más detalles, consulta la documentación sobre las atribuciones.

Controla el indicador de actividad de red

Para controlar el indicador de actividad de red en la barra de estado de las aplicaciones, debes implementar los métodos de delegado opcionales adecuados para la clase de autocompletado que estés usando y activar o desactivar el indicador de red por tu cuenta.

  • Para GMSAutocompleteViewController, debes implementar los métodos delegados didRequestAutocompletePredictions: y didUpdateAutocompletePredictions:.
  • Para GMSAutocompleteResultsViewController, debes implementar los métodos delegados didRequestAutocompletePredictionsForResultsController: y didUpdateAutocompletePredictionsForResultsController:.
  • Para GMSAutocompleteTableDataSource, debes implementar los métodos delegados didRequestAutocompletePredictionsForTableDataSource: y didUpdateAutocompletePredictionsForTableDataSource:.

Si implementas estos métodos y configuras [UIApplication sharedApplication].networkActivityIndicatorVisible como YES y NO, respectivamente, la barra de estado coincidirá correctamente con la IU de la función de autocompletar.

Restringe los resultados de la función de autocompletar

Puedes configurar el control de la IU de Autocomplete para restringir los resultados a una región geográfica específica o filtrar los resultados por uno o más tipos de lugar, o bien por uno o más países específicos. Para restringir los resultados, puedes hacer lo siguiente:

  • Para preferir (personalizar) los resultados dentro de la región definida, establece locationBias en GMSAutocompleteFilter (es posible que se muestren algunos resultados fuera de la región definida). Si también se establece locationRestriction, se ignorará locationBias.
  • Para mostrar solo (restringir) los resultados dentro de la región definida, establece locationRestriction en GMSAutocompleteFilter (solo se mostrarán los resultados dentro de la región definida).

    • Nota: Esta restricción solo se aplica a las rutas completas. Los resultados sintéticos ubicados fuera de los límites rectangulares se pueden mostrar solo si la ruta correspondiente se superpone con la restricción de ubicación.
  • Para que solo se muestren los resultados que se ajusten a un tipo de lugar específico, establece types en GMSAutocompleteFilter (por ejemplo, si especificas kGMSPlaceTypeCollectionAddress, el widget solo mostrará los resultados con una dirección exacta).

  • Para mostrar solo los resultados de hasta cinco países especificados, establece countries en GMSAutocompleteFilter.

Personaliza los resultados según una región específica

Para preferir (personalizar) los resultados dentro de la región definida, establece locationBias en el objeto GMSAutocompleteFilter, como se muestra aquí:

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

Restringe los resultados a una región específica

Para mostrar solo (restringir) los resultados dentro de la región definida, establece locationRestriction en GMSAutocompleteFilter, como se muestra aquí:

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

Filtrar los resultados por país

Para filtrar los resultados en un máximo de cinco países especificados, establece countries en GMSAutocompleteFilter, como se muestra aquí:

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

Filtrar los resultados por tipo de lugar o colección de tipos

Establece la propiedad types de GMSAutoCompleteFilter para restringir los resultados a un tipo o una colección de tipos determinados. Usa esta propiedad para especificar los filtros que se indican en las tablas 1, 2 y 3 de Tipos de lugar. Si no se especifica nada, se devolverán todos los tipos.

Para especificar un filtro de tipo o colección de tipos, haz lo siguiente:

  • Usa la propiedad types para especificar hasta cinco valores de type de la Tabla 1 y la Tabla 2 que se muestran en Tipos de lugar. Los valores de tipo se definen con las constantes en GMSPlaceType.

  • Usa la propiedad types para especificar una colección de tipos de la tabla 3 que se muestra en Tipos de lugares. Los valores de la colección de tipos se definen con las constantes en GMSPlaceType.

    Solo se permite un tipo de la Tabla 3 en la solicitud. Si especificas un valor de la Tabla 3, no puedes especificar un valor de la Tabla 1 o de la Tabla 2. Si lo haces, se producirá un error.

Por ejemplo, para que solo se devuelvan los resultados que se ajusten a un tipo de lugar en particular, establece types en GMSAutocompleteFilter. En el siguiente ejemplo, se muestra cómo configurar el filtro para que solo se devuelvan resultados con una dirección precisa:

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

Optimización de Place Autocomplete (heredada)

En esta sección, se describen algunas prácticas recomendadas que te ayudarán a aprovechar al máximo el servicio Place Autocomplete (heredado).

A continuación, se indican algunos lineamientos generales:

  • La forma más rápida de desarrollar una interfaz de usuario funcional es usar el widget de Place Autocomplete (heredado) de la API de Maps JavaScript, el widget de Place Autocomplete (heredado) del SDK de Places para Android o el control de la IU de Place Autocomplete (heredado) del SDK de Places para iOS.
  • Comprende los campos de datos esenciales de Place Autocomplete (heredado) desde el principio.
  • Los campos de restricción y personalización de la ubicación son opcionales, pero pueden afectar significativamente el rendimiento del autocompletado.
  • Usa el procedimiento de manejo de errores para asegurarte de que tu app administre el problema de forma adecuada si la API muestra un error.
  • Asegúrate de que tu app gestione correctamente los problemas cuando no haya selección y ofrezca a los usuarios una manera de continuar.

Prácticas recomendadas para la optimización de los costos

Optimización básica de los costos

Para optimizar el costo de usar el servicio Place Autocomplete (heredado), usa máscaras de campo en los widgets de Place Details (heredado) y Place Autocomplete (heredado), que te permiten mostrar solo los campos de datos de Place Autocomplete (heredado) que necesitas.

Optimización avanzada de los costos

Considera utilizar la implementación programática de Place Autocomplete (heredada) para acceder a los precios del SKU: Autocomplete, por solicitud y solicitar resultados de la API de Geocoding sobre el lugar seleccionado en lugar de utilizar Place Details (heredada). Los precios por solicitud asociados con la API de Geocoding son más rentables que los precios por sesión (basados en sesión) si se cumplen las siguientes condiciones:

  • Si solo necesitas las coordenadas de latitud y longitud, o la dirección del lugar seleccionado por el usuario, la API de Geocoding proporciona esta información de manera más fácil que una llamada a Place Details (heredada).
  • Si los usuarios seleccionan una predicción de autocompletar con un promedio de cuatro solicitudes de predicciones de Place Autocomplete (heredada) o menos, el precio por solicitud puede ser más rentable que el precio por sesión.
Para elegir la implementación de Place Autocomplete (heredada) que tenga el costo más bajo para tu aplicación, busca la fila de la siguiente tabla que coincida con las necesidades de tu aplicación.
Qué necesita tu aplicación Cantidad promedio de solicitudes de Place Autocomplete (heredada) antes de que un usuario seleccione una predicción Implementación recomendada
Detalles del lugar que no sean la dirección ni la ubicación, como el nombre del lugar, el estado de la empresa o el horario de atención Cualquier número Place Autocomplete basado en sesiones (heredado) con Place Details (heredado)
Solo la dirección y las coordenadas de latitud o longitud de la predicción seleccionada Cuatro o menos Place Autocomplete (heredado) por solicitud con la API de Geocoding
Solo la dirección y las coordenadas de latitud o longitud de la predicción seleccionada Más de cuatro Place Autocomplete basado en sesiones (heredado) para aplicaciones que solo usan direcciones

La API de Geocoding podría ser una opción más rentable que Place Details (heredada) para tu aplicación, según el rendimiento de su uso de Place Autocomplete (heredada). La eficiencia de Place Autocomplete (heredado) de cada aplicación varía según las búsquedas que ingresan los usuarios, dónde se usa la aplicación y si se siguen las prácticas recomendadas de optimización del rendimiento.

Para encontrar la cantidad promedio de solicitudes de la tabla, analiza cuántos caracteres escribe un usuario en promedio antes de seleccionar una predicción de Place Autocomplete (heredada) en tu aplicación.

Place Autocomplete basado en sesiones (heredado) con Place Details (heredado)

Usa el servicio Place Autocomplete (heredado) basado en sesiones con Place Details (heredado).
Dado que tu aplicación requiere Place Details (heredado), como el nombre del lugar, el estado de la empresa o el horario de atención, tu implementación de Place Autocomplete (heredado) debe usar un token de sesión (de manera programática o integrado en los widgets de JavaScript, Android o iOS) por sesión más los SKUs de datos de Places aplicables, según los campos de datos de lugar que solicites.1

Implementación de widgets
La administración de sesiones está integrada automáticamente en los widgets de JavaScript, Android o iOS. Esto incluye las solicitudes de Place Autocomplete (heredada) y Place Details (heredada) en la predicción seleccionada. Asegúrate de especificar el parámetro fields para asegurarte de solicitar únicamente los campos de datos de Place Autocomplete (heredado) que necesitas.

Implementación programática
Usa un token de sesión con tus solicitudes de Place Autocomplete (heredada). Cuando solicites la predicción seleccionada a Place Details (heredado), incluye los siguientes parámetros:

  1. El ID de lugar de la respuesta de Place Autocomplete (heredada)
  2. El token de sesión que se utilizó en la solicitud de Place Autocomplete (heredada)
  3. El parámetro fields que especifica los campos de datos de Place Autocomplete (heredado) que necesitas

Place Autocomplete (heredado) por solicitud con la API de Geocoding

Implementa Place Autocomplete (heredado) de manera programática sin tokens de sesión y llama a la API de Geocoding en la predicción de lugar seleccionada.
La API de Geocoding proporciona direcciones y coordenadas de latitud y longitud. Realizar cuatro solicitudes de Autocomplete por solicitud más una llamada a la API de Geocoding sobre la predicción de lugar seleccionada es menos que el costo por sesión de Place Autocomplete (heredado).1

Considera aplicar las prácticas recomendadas de rendimiento para ayudar a los usuarios a obtener la predicción que buscan con menos caracteres.

Place Autocomplete (heredado) basado en sesiones para aplicaciones que solo usan direcciones

Usa el servicio Place Autocomplete (heredado) basado en sesiones con Place Details (heredado).
Dado que la cantidad promedio de solicitudes que esperas realizar antes de que un usuario seleccione una predicción de Place Autocomplete (heredada) supera el costo de los precios por sesión, tu implementación de Place Autocomplete (heredada) debe usar un token de sesión para las solicitudes de Place Autocomplete (heredada) y la solicitud de Place Details (heredada) asociada por sesión. 1

Implementación de widgets
La administración de sesiones está integrada automáticamente en los widgets de JavaScript, Android o iOS. Esto incluye las solicitudes de Place Autocomplete (heredada) y Place Details (heredada) en la predicción seleccionada. Asegúrate de especificar el parámetro fields para asegurarte de solicitar únicamente los campos que necesitas.

Implementación programática
Usa un token de sesión con tus solicitudes de Place Autocomplete (heredada). Cuando solicites la predicción seleccionada a Place Details (heredado), incluye los siguientes parámetros:

  1. El ID de lugar de la respuesta de Place Autocomplete (heredada)
  2. El token de sesión que se utilizó en la solicitud de Place Autocomplete (heredada)
  3. El parámetro fields que especifica campos de datos básicos, como la dirección y la geometría

Considera retrasar las solicitudes de Place Autocomplete (heredada)
Puedes emplear estrategias como demorar una solicitud de Place Autocomplete (heredada) hasta que el usuario escriba los primeros tres o cuatro caracteres para que tu aplicación realice menos solicitudes. Por ejemplo, realizar solicitudes de Place Autocomplete (heredada) para cada carácter después de que el usuario haya escrito el tercer carácter significa que, si el usuario escribe siete caracteres y, luego, selecciona una predicción para la que realizas una solicitud a la API de Geocoding, el costo total sería de 4 solicitudes de Place Autocomplete (heredada) por solicitud + Geocoding.1

Si retrasar las solicitudes puede hacer que tu solicitud programática promedio sea inferior a cuatro, puedes seguir las instrucciones para implementar Place Autocomplete (heredada) con la API de Geocoding y obtener un rendimiento optimizado. Ten en cuenta que demorar las solicitudes puede percibirse como latencia por parte del usuario, que tal vez espere ver predicciones con cada letra que ingresa.

Considera seguir las prácticas recomendadas de rendimiento para ayudar a los usuarios a obtener la predicción que buscan con menos caracteres.


  1. Para conocer los costos, consulta las listas de precios de Google Maps Platform.

Prácticas recomendadas para el rendimiento

Los siguientes lineamientos describen maneras de optimizar el rendimiento de Place Autocomplete (versión heredada):

  • Agrega restricciones por país, personalización de la ubicación y, en el caso de las implementaciones programáticas, la preferencia de idioma a la implementación de Place Autocomplete (heredada). La preferencia de idioma no es necesaria para los widgets, dado que toman esta información del navegador o el dispositivo móvil del usuario.
  • Si Place Autocomplete (heredado) cuenta con un mapa, puedes personalizar la ubicación según su viewport.
  • En las situaciones en que un usuario no elige una de las predicciones de Place Autocomplete (heredada), generalmente, porque ninguna de ellas indica la dirección de resultado deseada, puedes reutilizar la entrada original del usuario para tratar de obtener resultados más relevantes:
    • Si esperas que el usuario ingrese únicamente información sobre la dirección, vuelve a usar su entrada original en una llamada a la API de Geocoding.
    • Si esperas que el usuario ingrese búsquedas para un lugar específico por nombre o dirección, usa una solicitud de Place Details (heredada). Si se espera que los resultados pertenezcan únicamente a una región específica, usa la restricción de ubicación.
    A continuación, indicamos otras situaciones en las que es mejor recurrir a la API de Geocoding:
    • Usuarios que ingresan direcciones de sublocales, como direcciones de unidades o departamentos específicos dentro de un edificio Por ejemplo, la dirección checa "Stroupežnického 3191/17, Praha" genera una predicción parcial en Place Autocomplete (heredado).
    • Usuarios que ingresan direcciones con prefijos de tramo de ruta, como "23-30 29th St, Queens" en la ciudad de Nueva York o "47-380 Kamehameha Hwy, Kaneohe" en la isla de Kauai en Hawái

Sesgo de ubicación

Personaliza los resultados para un área específica pasando los parámetros location y radius. Esto le indica a Place Autocomplete (heredado) que prefiera mostrar resultados dentro del área definida. Es posible que también se muestren resultados externos al área definida. Puedes usar el parámetro includedRegionCodes para filtrar los resultados y mostrar solo los lugares que se encuentran dentro de un país específico.

Restricción de ubicación

Restringe los resultados a un área específica pasando un parámetro locationRestriction.

También puedes restringir los resultados a la región definida por location y un parámetro radius agregando el parámetro strictbounds. Esto le indica a Place Autocomplete (heredado) que devuelva solo los resultados dentro de esa región.

Solución de problemas

Aunque puede ocurrir una gran variedad de errores, la mayoría de los que probablemente experimente tu app suelen deberse a errores de configuración (por ejemplo, se usó una clave de API incorrecta o se configuró de forma incorrecta) o errores de cuota (tu app superó su cuota). Consulta Límites de uso para obtener más información sobre las cuotas.

Los errores que se producen durante el uso de los controles de autocompletado se devuelven en el método didFailAutocompleteWithError() de los distintos protocolos de delegado. La propiedad code del objeto NSError proporcionado se establece en uno de los valores de la enumeración GMSPlacesErrorCode.