Eso es todo.

Para comenzar a desarrollar, consulta nuestra documentación para desarrolladores.

Activar la Google Places API for iOS

Para que puedas comenzar, te proporcionaremos orientación en la consola para desarrolladores de Google a fin de que hagas primero algunas acciones:

  1. Crear o seleccionar un proyecto
  2. Activar la Google Places API for iOS
  3. Crear claves correspondientes
Continuar

Autocompletado de sitios

El servicio de autocompletado de Google Places API for iOS muestra predicciones del sitio en respuesta a consultas de búsqueda de usuarios. A medida que el usuario escribe, el servicio de autocompletado muestra sugerencias para lugares; por ejemplo, negocios, direcciones y puntos de interés.

Puedes agregar el autocompletado a tu app de las siguientes formas:

Agregar un control de IU de autocompletado

El control de IU de autocompletado es un cuadro de diálogo de búsqueda con funcionalidad de autocompletado incorporada. Cuando un usuario ingresa términos de búsqueda, el control presenta una lista de lugares de predicción seleccionables. Cuando el usuario elige una opción, se muestra una instancia de GMSPlace, que tu app luego puede usar para obtener información sobre el lugar seleccionado.

Puedes agregar el control de IU de autocompletado a tu app de las siguientes maneras:

Agregar un control de pantalla completa

Usa el control de pantalla completa cuando desees un contexto modal, en el cual la IU de autocompletado reemplace temporalmente la IU de tu app hasta que el usuario realice su selección. Esta funcionalidad está a cargo de la clase GMSAutocompleteViewController. Cuando el usuario selecciona un sitio, tu app recibe un callback.

Para agregar el control de pantalla completa a tu app:

  1. Crea un elemento de IU en tu app principal para iniciar el control de IU de autocompletado; por ejemplo, un controlador táctil en un UIButton.
  2. Implementa el protocolo GMSAutocompleteViewControllerDelegate en el controlador de vista principal.
  3. Crea una instancia de GMSAutocompleteViewController y asigna el controlador de vista principal como propiedad de delegado.
  4. Presenta GMSAutocompleteViewController usando [self presentViewController...].
  5. Administra la selección del usuario en el método de delegado didAutocompleteWithPlace.
  6. Ignora el controlador en los métodos de delegado didAutocompleteWithPlace, didFailAutocompleteWithError y wasCancelled.

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

Swift

import UIKit
import GooglePlaces

class ViewController: UIViewController {

  // Present the Autocomplete view controller when the button is pressed.
  @IBAction func autocompleteClicked(_ sender: UIButton) {
    let autocompleteController = GMSAutocompleteViewController()
    autocompleteController.delegate = self
    present(autocompleteController, animated: true, completion: nil)
  }
}

extension ViewController: GMSAutocompleteViewControllerDelegate {

  // Handle the user's selection.
  func viewController(_ viewController: GMSAutocompleteViewController, didAutocompleteWith place: GMSPlace) {
    print("Place name: \(place.name)")
    print("Place address: \(place.formattedAddress)")
    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/GooglePlaces.h>

@interface ViewController () <GMSAutocompleteViewControllerDelegate>

@end

@implementation ViewController

...

// Present the autocomplete view controller when the button is pressed.
- (IBAction)onLaunchClicked:(id)sender {
  GMSAutocompleteViewController *acController = [[GMSAutocompleteViewController alloc] init];
  acController.delegate = self;
  [self presentViewController:acController animated:YES completion:nil];
}

// 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 address %@", place.formattedAddress);
  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

Agregar 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 alterna dinámicamente la visibilidad de la lista de resultados según el enfoque de la IU de entrada.

Para agregar un controlador de resultados a tu app:

  1. Crea un GMSAutocompleteResultsViewController.
  2. Implementa el protocolo GMSAutocompleteResultsViewControllerDelegate en el controlador de vista principal y asigna dicho controlador como propiedad de delegado.
  3. Crea un objeto UISearchController y pasa el GMSAutocompleteResultsViewController como argumento del controlador de resultados.
  4. Configura GMSAutocompleteResultsViewController como propiedad searchResultsUpdater del UISearchController.
  5. Agrega searchBar para el UISearchController a la IU de tu app.
  6. Administra la selección del usuario en el método de delegado didAutocompleteWithPlace.

Existen diversas formas de disponer la barra de búsqueda de un UISearchController en la IU de tu app:

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

En el siguiente ejemplo de código, se muestra la manera de agregar un controlador de resultados, agregar searchBar a la barra de navegación y administrar 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;
}

Nota: Para que la barra de búsqueda se muestre correctamente, el controlador de vista de tu app debe estar dentro de un UINavigationController.

Agregar una barra de búsqueda a la parte superior de una vista

En el siguiente ejemplo de código, se muestra la manera de agregar la 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 manera predeterminada, UISearchController oculta la barra de navegación en la presentación (esto se puede inhabilitar). En los casos en los que la barra de navegación está visible y su color es opaco, UISearchController no establece la ubicación de manera correcta. 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;

Agregar una barra de búsqueda usando resultados de elementos emergentes

En el siguiente ejemplo de código, se muestra la manera de disponer una barra de búsqueda en el lado derecho de la barra de navegación y de mostrar resultados en un elemento 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;
}

Nota: Para que la barra de búsqueda se muestre correctamente, el controlador de vista de tu app debe estar dentro de un UINavigationController.

Usar una fuente de datos de tabla

Si tu app debe ser compatible con iOS 7, puedes usar la clase GMSAutocompleteTableDataSource para que aparezca la vista de tabla de un UISearchDisplayController.

A fin de usar GMSAutocompleteTableDataSource para mostrar un controlador de búsqueda:

  1. Implementa los protocolos GMSAutocompleteTableDataSourceDelegate y UISearchDisplayDelegate en el controlador de vista principal.
  2. Crea una instancia de GMSAutocompleteTableDataSource y asigna el controlador de vista principal como propiedad de delegado.
  3. Crea una instancia de UISearchDisplayController.
  4. Agrega searchBar para el UISearchController a la IU de tu app.
  5. Administra la selección del usuario en el método de delegado didAutocompleteWithPlace.
  6. Ignora el controlador en los métodos de delegado didAutocompleteWithPlace, didFailAutocompleteWithError y wasCancelled.

En el siguiente ejemplo de código, se muestra la manera de usar la clase GMSAutocompleteTableDataSource para que aparezca la vista de tabla de un UISearchDisplayController.

Swift

import UIKit
import GooglePlaces

class ViewController: UIViewController, UISearchDisplayDelegate {

  var searchBar: UISearchBar?
  var tableDataSource: GMSAutocompleteTableDataSource?
  var searchDisplayController: UISearchDisplayController?

  override func viewDidLoad() {
    super.viewDidLoad()

    searchBar = UISearchBar(CGRect(x: 0, y: 0, width: 250.0, height: 44.0))

    tableDataSource = GMSAutocompleteTableDataSource()
    tableDataSource?.delegate = self

    searchDisplayController = UISearchDisplayController(searchBar: searchBar!, contentsController: self)
    searchDisplayController?.searchResultsDataSource = tableDataSource
    searchDisplayController?.searchResultsDelegate = tableDataSource
    searchDisplayController?.delegate = self

    view.addSubview(searchBar!)
  }

  func didUpdateAutocompletePredictionsForTableDataSource(tableDataSource: GMSAutocompleteTableDataSource) {
    // Turn the network activity indicator off.
    UIApplication.sharedApplication().networkActivityIndicatorVisible = false
    // Reload table data.
    searchDisplayController?.searchResultsTableView.reloadData()
  }

  func didRequestAutocompletePredictionsForTableDataSource(tableDataSource: GMSAutocompleteTableDataSource) {
    // Turn the network activity indicator on.
    UIApplication.sharedApplication().networkActivityIndicatorVisible = true
    // Reload table data.
    searchDisplayController?.searchResultsTableView.reloadData()
  }

}

extension ViewController: GMSAutocompleteTableDataSourceDelegate {
  func tableDataSource(tableDataSource: GMSAutocompleteTableDataSource, didAutocompleteWithPlace place: GMSPlace) {
    searchDisplayController?.active = false
    // Do something with the selected place.
    print("Place name: \(place.name)")
    print("Place address: \(place.formattedAddress)")
    print("Place attributions: \(place.attributions)")
  }

  func searchDisplayController(controller: UISearchDisplayController, shouldReloadTableForSearchString searchString: String?) -> Bool {
    tableDataSource?.sourceTextHasChanged(searchString)
    return false
  }

  func tableDataSource(tableDataSource: GMSAutocompleteTableDataSource, didFailAutocompleteWithError error: NSError) {
    // TODO: Handle the error.
    print("Error: \(error.description)")
  }

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

Objective-C

- (void)viewDidLoad {
  [super viewDidLoad];
  // Do any additional setup after loading the view, typically from a nib.

  _searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 20, 250.0f, 44.0f)];

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

  _searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:_searchBar
                                                               contentsController:self];
  _searchDisplayController.searchResultsDataSource = _tableDataSource;
  _searchDisplayController.searchResultsDelegate = _tableDataSource;
  _searchDisplayController.delegate = self;

  [self.view addSubview:_searchBar];
}

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString
{
  [_tableDataSource sourceTextHasChanged:searchString];
  return NO;
}

// Handle the user's selection.
- (void)tableDataSource:(GMSAutocompleteTableDataSource *)tableDataSource
  didAutocompleteWithPlace:(GMSPlace *)place {
  [_searchDisplayController setActive:NO animated:YES];
  // Do something with the selected place.
  NSLog(@"Place name %@", place.name);
  NSLog(@"Place address %@", place.formattedAddress);
  NSLog(@"Place attributions %@", place.attributions.string);
}

- (void)tableDataSource:(GMSAutocompleteTableDataSource *)tableDataSource
  didFailAutocompleteWithError:(NSError *)error {
  [_searchDisplayController setActive:NO animated:YES];
  // TODO: handle the error.
  NSLog(@"Error: %@", [error description]);
}

- (void)didUpdateAutocompletePredictionsForTableDataSource:
  (GMSAutocompleteTableDataSource *)tableDataSource {
  // Turn the network activity indicator off.
  [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
  // Reload table data.
  [_searchDisplayController.searchResultsTableView reloadData];
}

- (void)didRequestAutocompletePredictionsForTableDataSource:
  (GMSAutocompleteTableDataSource *)tableDataSource {
  // Turn the network activity indicator on.
  [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
  // Reload table data.
  [_searchDisplayController.searchResultsTableView reloadData];
}

Nota: La API de UISearchDisplayController no es compatible con el concepto de actualizaciones de datos asincrónicas, por lo cual es necesario forzar actualizaciones de tabla mediante una nueva carga de los datos de tabla en los métodos didUpdateAutocompletePredictions y didRequestAutocompletePredictions del protocolo GMSAutoCompleteResultsDelegate.

Personalizar colores de texto y fondos

Puedes configurar los colores de todo el texto y todos los fondos del control de IU de autocompletado, a fin de que el widget coincida con la apariencia visual de tu app con mayor precisión. Existen dos formas de configurar los colores del control de IU:

  • Mediante el uso del protocolo UIAppearance de iOS nativo, para personalizar el estilo de los controles de IU de forma global siempre que sea posible. Esta configuración se aplica a muchos de los elementos del control de IU, aunque no a todos.
  • Mediante el uso de los métodos de SDK en las clases de widget, para configurar las propiedades que no son compatibles con el protocolo UIAppearance.

Comúnmente, tu app usará cierta combinación del protocolo UIAppearance y de los métodos de SDK. En el siguiente diagrama, se muestran los elementos cuyo estilo se puede personalizar:

Colores del control de IU de autocompletado

En la siguiente tabla, se muestra una lista de todos los elementos de la IU y se indica la forma en que se puede personalizar el estilo de cada uno (protocolo UIAppearance o método SDK).

Elemento de la IU Método Cómo personalizar el estilo
Matiz de la barra de navegación (fondo) Protocolo UIAppearance Llama a setBarTintColor en el proxy UINavigationBar.
Color de matiz de la barra de navegación (cuadro de texto de la barra de búsqueda y botón Cancel) Protocolo UIAppearance Llama a setTintColor en el proxy UINavigationBar.
Color de texto de la barra de búsqueda Protocolo UIAppearance Configura NSForegroundColorAttributeName en searchBarTextAttributes.
Color de matiz de la barra de búsqueda N/D La barra de búsqueda es translúcida y se mostrará como una versión sombreada de la barra de navegación.
Color del texto del marcador de posición de la barra de búsqueda (texto de búsqueda predeterminado) Protocolo UIAppearance Configura NSForegroundColorAttributeName en placeholderAttributes.
Texto principal (también se aplica al texto correspondiente a errores y mensajes) Método SDK Llama a primaryTextColor.
Resalto del texto principal Método SDK Llama a primaryTextHighlightColor.
Texto secundario Método SDK Llama a secondaryTextColor.
Texto de error y mensaje Método SDK Llama a primaryTextColor.
Fondo de celda de tabla Método SDK Llama a tableCellBackgroundColor.
Color de separador de celda de tabla Método SDK Llama a tableCellSeparatorColor.
Botón “Try Again” Método SDK Llama a tintColor.
Indicador de actividad (indicador de progreso) Protocolo UIAppearance Llama a setColor en el proxy UIActivityIndicatorView.
Logotipo “Con la tecnología de Google”, imagen de nube triste N/D La versión blanca o gris se selecciona automáticamente según el contraste del fondo.
Íconos de lupa y eliminación de texto en el campo de texto de la barra de búsqueda N/D Para aplicar ajustes estilo, reemplaza las imágenes predeterminadas con imágenes del color deseado.

Nota: Estas propiedades solo afectan la configuración de color de los elementos de la IU. No se puede modificar el tamaño de los elementos de la IU ni la fuente usada en las celdas de las tablas.

Utilizar el protocolo UIAppearance

Puedes usar el protocolo UIAppearance para obtener el proxy de apariencia para un elemento determinado de la IU, que luego puedes emplear para configurar el color de dicho elemento. Cuando se realiza una modificación, se ven afectadas todas las instancias de un elemento determinado de la IU. Por ejemplo, en el siguiente caso, el color del texto de las clases UITextField cambia a verde de manera global cuando estas están contenidas en una 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 sobre la clase UIColor.

En los siguientes fragmentos de código, se muestran todos los comandos de proxy que debes usar para aplicar ajustes de estilo a todos los elementos del control de IU de autocompletado de 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;

Configurar las propiedades de estilo del control de IU

Un subconjunto de elementos de control de 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 la forma de definir colores de primer y segundo plano, y de aplicarlos a una instancia de control de IU denominada acController. Agrega este código al método onLaunchClicked en ViewController.m:

UIColor <em>darkGray = [UIColor darkGrayColor];
UIColor </em>lightGray = [UIColor lightGrayColor];</p>
<p>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;

Nota: En el caso de GMSAutocompleteViewController y GMSAutocompleteResultsViewController, puedes usar Interface Builder para configurar estos valores.

Obtener predicciones del sitio mediante programación

Puedes crear una IU de búsqueda personalizada como alternativa a la IU que se proporciona en el widget de autocompletado. Para ello, tu app debe obtener predicciones del sitio mediante programación. Tu app puede obtener una lista de nombres de lugares o direcciones de predicción de una de las siguientes formas:

Llamar a GMSPlacesClient

Para obtener una lista de nombres de lugares o direcciones de predicción, llama al método GMSPlacesClient autocompleteQuery:bounds:filter:callback: con los siguientes parámetros:

  • Una string de autocompleteQuery que contenga el texto que ingresó el usuario.
  • Un objeto GMSCoordinateBounds que restrinja los resultados a un área específica según límites de latitud y longitud.
  • Un GMSAutocompleteFilter que restrinja los resultados a un tipo de sitio específico. Para recuperar todos los tipos, proporciona un valor de nil. El filtro admite los siguientes tipos de sitios:

    • kGMSPlacesAutocompleteTypeFilterNoFilter: filtro vacío; se muestran todos los resultados.
    • kGMSPlacesAutocompleteTypeFilterGeocode: muestra solo resultados de geocodificación, en lugar de resultados de negocios. Usa esta solicitud para eliminar ambigüedades en los resultados en los cuales la ubicación especificada puede ser indeterminada.
    • kGMSPlacesAutocompleteTypeFilterAddress: muestra solo resultados de autocompletado con una dirección exacta. Usa este tipo cuando sepas que el usuario buscará una dirección especificada con precisión.
    • kGMSPlacesAutocompleteTypeFilterEstablishment: muestra solo sitios correspondientes a negocios.
    • kGMSPlacesAutocompleteTypeFilterRegion: muestra solo sitios que coinciden con uno de los siguientes tipos:

      • locality
      • sublocality
      • postal_code
      • country
      • administrative_area_level_1
      • administrative_area_level_2
    • kGMSPlacesAutocompleteTypeFilterCity: muestra solo resultados que coinciden con locality o administrative_area_level_3.

Para obtener más información, consulta tipos de sitios.

  • También debes incluir un método callback para manejar las predicciones mostradas.

En los ejemplos de código siguientes, se muestra una llamada simplificada a autocompleteQuery:bounds:filter:callback:.

Swift

func placeAutocomplete() {
  let filter = GMSAutocompleteFilter()
  filter.type = .establishment
  placesClient.autocompleteQuery("Sydney Oper", bounds: nil, filter: filter, callback: {(results, error) -> Void 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

- (void)placeAutocomplete {

GMSAutocompleteFilter *filter = [[GMSAutocompleteFilter alloc] init];
filter.type = kGMSPlacesAutocompleteTypeFilterEstablishment;

[_placesClient autocompleteQuery:@"Sydney Oper"
                          bounds:nil
                          filter:filter
                        callback:^(NSArray *results, NSError *error) {
                          if (error != nil) {
                            NSLog(@"Autocomplete error %@", [error localizedDescription]);
                            return;
                          }

                          for (GMSAutocompletePrediction* result in results) {
                            NSLog(@"Result '%@' with placeID %@", result.attributedFullText.string, result.placeID);
                          }
                        }];
}

La API invoca el método de callback especificado y pasa un conjunto de objetos GMSAutocompletePrediction.

Cada objeto GMSAutocompletePrediction contiene la siguiente información:

  • attributedFullText: texto completo de la predicción, con la forma de un objeto NSAttributedString. Por ejemplo, “Ópera de Sídney, Sídney, Nueva Gales del Sur, Australia”. Cada intervalo de texto que coincide con la entrada del usuario tiene un atributo: kGMSAutocompleteMatchAttribute. Puedes usar este atributo para destacar el texto de coincidencia en la consulta del usuario, por ejemplo, como se muestra a continuación.
  • placeID: ID del sitio de predicción. Un ID de sitio es un identificador textual que identifica de forma exclusiva un sitio. Para obtener más información sobre los ID de sitio, consulta la información general sobre ID de sitio.

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

Usar la herramienta de buscador

Si deseas compilar tu propio control de autocompletado desde cero, puedes usar GMSAutocompleteFetcher, que encapsula el método autocompleteQuery en GMSPlacesClient. La herramienta de buscador limita las solicitudes y muestra solo resultados para el texto de búsqueda ingresado más recientemente. No ofrece elementos de IU.

Para implementar GMSAutocompleteFetcher, ten en cuenta los siguientes pasos:

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

En el siguiente ejemplo de código, se muestra la manera de usar dicha herramienta para tomar la entrada del usuario y mostrar coincidencias de sitios en una vista de texto. Se omitió la funcionalidad para seleccionar un sitio. 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)
    let bounds = GMSCoordinateBounds(coordinate: neBoundsCorner,
                                     coordinate: swBoundsCorner)

    // Set up the autocomplete filter.
    let filter = GMSAutocompleteFilter()
    filter.type = .establishment

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

    textField = UITextField(frame: CGRect(x: 5.0, y: 10.0,
                                          width: view.bounds.size.width - 5.0,
                                          height: 44.0))
    textField?.autoresizingMask = .flexibleWidth
    textField?.addTarget(self, action: #selector(textFieldDidChange(textField:)),
                         for: .editingChanged)

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

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

  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", prediction.attributedPrimaryText)
    }

    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);
  GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithCoordinate:neBoundsCorner
                                                                     coordinate:swBoundsCorner];

  // Set up the autocomplete filter.
  GMSAutocompleteFilter *filter = [[GMSAutocompleteFilter alloc] init];
  filter.type = kGMSPlacesAutocompleteTypeFilterEstablishment;

  // Create the fetcher.
  _fetcher = [[GMSAutocompleteFetcher alloc] initWithBounds:bounds
                                                     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

Configurar los GMSCoordinateBounds del autocompletado

Puedes proporcionar un GMSCoordinateBounds al autocompletado para orientar las acciones de compleción. Por ejemplo, si ya tienes un mapa de Google en tu controlador de vista, puedes usar los límites de la ventana de visualización actual para restringir los resultados de autocompletado.

Swift

func placeAutocomplete() {
  let visibleRegion = mapView.projection.visibleRegion()
  let bounds = GMSCoordinateBounds(coordinate: visibleRegion.farLeft, coordinate: visibleRegion.nearRight)

  let filter = GMSAutocompleteFilter()
  filter.type = .establishment
  placesClient.autocompleteQuery("Sydney Oper", bounds: bounds, filter: filter, callback: {
    (results, error) -> Void in
    guard error == nil else {
      print("Autocomplete error \(error)")
      return
    }
    if let results = results {
      for result in results {
        print("Result \(result.attributedFullText) with placeID \(result.placeID)")
      }
    }
  })
}

Objective-C

- (void)placeAutocomplete {

GMSVisibleRegion visibleRegion = self.mapView.projection.visibleRegion;
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithCoordinate:visibleRegion.farLeft
                                                                   coordinate:visibleRegion.nearRight];
GMSAutocompleteFilter *filter = [[GMSAutocompleteFilter alloc] init];
filter.type = kGMSPlacesAutocompleteTypeFilterEstablishment;

[_placesClient autocompleteQuery:@"Sydney Oper"
                          bounds:bounds
                          filter:filter
                        callback:^(NSArray *results, NSError *error) {
                          if (error != nil) {
                            NSLog(@"Autocomplete error %@", [error localizedDescription]);
                            return;
                          }

                          for (GMSAutocompletePrediction* result in results) {
                            NSLog(@"Result '%@' with placeID %@", result.attributedFullText.string, result.placeID);
                          }
                        }];
}

Límites de uso

Mostrar atribuciones en tu app

  • Si tu app usa el servicio de autocompletado mediante programación, tu IU debe mostrar una atribución “Con la tecnología de Google” o aparecer dentro de un mapa de la marca Google.
  • Si tu app usa el control de IU de autocompletado, no se requiere ninguna acción adicional (la atribución requerida se muestra de manera predeterminada). Si recuperas y muestras información adicional del sitio después de obtener un sitio mediante ID, también debes mostrar atribuciones de terceros.

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

Control del indicador de actividad de red

A fin de controlar el indicador de actividad de red en la barra de estado de la aplicación, debes implementar los métodos de delegado opcionales correspondientes para la clase de autocompletado que uses, y activar y desactivar el indicador de red tú mismo.

  • En el caso de GMSAutocompleteViewController, debes implementar los métodos de delegado didRequestAutocompletePredictions: y didUpdateAutocompletePredictions:.
  • En el caso de GMSAutocompleteResultsViewController, debes implementar los métodos de delegado didRequestAutocompletePredictionsForResultsController: y didUpdateAutocompletePredictionsForResultsController:.
  • En el caso de GMSAutocompleteTableDataSource, debes implementar los métodos de delegado didRequestAutocompletePredictionsForTableDataSource: y didUpdateAutocompletePredictionsForTableDataSource:.

Mediante la implementación de estos métodos y la configuración de [UIApplication sharedApplication].networkActivityIndicatorVisible en YES y NO respectivamente, la barra de estado coincidirá correctamente con la IU de autocompletado.

Solución de problemas

Si bien pueden producirse muchos errores diferentes, la mayoría de los que tu app puede experimentar se deben, por lo general, a errores de configuración (por ejemplo, se usó la clave de API incorrecta o la clave de API se configuró de forma incorrecta) o a errores de cuota (tu app excedió su cuota). Consulta Límites de uso para obtener más información sobre las cuotas.

Los errores que tienen lugar cuando se usan los controles de autocompletado se muestran en el método didFailAutocompleteWithError() de los diferentes protocolos de delegado. La propiedad code del objeto NSError proporcionado se fija en uno de los valores de la enumeración GMSPlacesErrorCode.

Enviar comentarios sobre…