Place Autocomplete

Le service de saisie semi-automatique du SDK Places pour iOS renvoie des prédictions de lieux en réponse aux requêtes de recherche des utilisateurs. À mesure que l'utilisateur saisit du texte, le service de saisie semi-automatique affiche des suggestions de lieux tels que des entreprises, des adresses, des codes Plus et des points d'intérêt.

Vous pouvez ajouter Autocomplete à votre application de plusieurs façons :

Ajouter une commande d'interface utilisateur pour la saisie semi-automatique

La commande d'interface utilisateur pour la saisie semi-automatique est une boîte de dialogue de recherche avec une fonctionnalité de saisie semi-automatique intégrée. À mesure qu'un utilisateur saisit des termes de recherche, le contrôle présente une liste de lieux prédits parmi lesquels il peut choisir. Lorsque l'utilisateur effectue une sélection, une instance GMSPlace est renvoyée. Votre application peut ensuite l'utiliser pour obtenir des informations sur le lieu sélectionné.

Pour ajouter la commande d'interface utilisateur Autocomplete à votre application, vous pouvez :

Ajouter une commande plein écran

Utilisez la commande plein écran lorsque vous souhaitez un contexte modal, où l'UI de saisie semi-automatique remplace temporairement l'UI de votre application jusqu'à ce que l'utilisateur ait fait son choix. Cette fonctionnalité est fournie par la classe GMSAutocompleteViewController. Lorsque l'utilisateur sélectionne un lieu, votre application reçoit un rappel.

Pour ajouter une commande plein écran à votre application :

  1. Créez un élément d'interface utilisateur dans votre application principale pour lancer la commande d'interface utilisateur de saisie semi-automatique, par exemple un gestionnaire d'événements tactiles sur un UIButton.
  2. Implémentez le protocole GMSAutocompleteViewControllerDelegate dans le contrôleur de vue parent.
  3. Créez une instance de GMSAutocompleteViewController et attribuez le contrôleur de vue parent en tant que propriété déléguée.
  4. Créez un GMSPlaceField pour définir les types de données de lieu à renvoyer.
  5. Ajoutez un GMSAutocompleteFilter pour limiter la requête à un type de lieu spécifique.
  6. Présentez GMSAutocompleteViewController à l'aide de [self presentViewController...].
  7. Gérez la sélection de l'utilisateur dans la méthode déléguée didAutocompleteWithPlace.
  8. Fermez le contrôleur dans les méthodes déléguées didAutocompleteWithPlace, didFailAutocompleteWithError et wasCancelled.

L'exemple suivant montre une manière possible de lancer GMSAutocompleteViewController en réponse à l'activation d'un bouton par l'utilisateur.

Swift

import UIKit
import GooglePlaces

class ViewController: UIViewController {

  override func viewDidLoad() {
    makeButton()
  }

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

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

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

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

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

}

extension ViewController: GMSAutocompleteViewControllerDelegate {

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

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

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

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

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

}

Objective-C

#import "ViewController.h"
@import GooglePlaces;

@interface ViewController () <GMSAutocompleteViewControllerDelegate>

@end

@implementation ViewController {
  GMSAutocompleteFilter *_filter;
}

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

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

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

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

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

  // Add a button to the view.
-   (void)makeButton{
  UIButton *btnLaunchAc = [UIButton buttonWithType:UIButtonTypeCustom];
  [btnLaunchAc addTarget:self
             action:@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

Ajouter un sélecteur de résultats

Utilisez un contrôleur de résultats pour mieux maîtriser l'interface utilisateur de saisie de texte. Le contrôleur de résultats active ou désactive dynamiquement la visibilité de la liste des résultats en fonction de la sélection de l'UI d'entrée.

Pour ajouter un contrôleur de résultats à votre application :

  1. Créez un GMSAutocompleteResultsViewController.
    1. Implémentez le protocole GMSAutocompleteResultsViewControllerDelegate dans le contrôleur de vue parent et attribuez le contrôleur de vue parent en tant que propriété déléguée.
  2. Créez un objet UISearchController en transmettant GMSAutocompleteResultsViewController en tant qu'argument du contrôleur de résultats.
  3. Définissez GMSAutocompleteResultsViewController comme propriété searchResultsUpdater de UISearchController.
  4. Ajoutez searchBar pour UISearchController à l'UI de votre application.
  5. Gérez la sélection de l'utilisateur dans la méthode déléguée didAutocompleteWithPlace.

Il existe plusieurs façons de placer la barre de recherche d'un UISearchController dans l'UI de votre application :

Ajouter une barre de recherche à la barre de navigation

L'exemple de code suivant montre comment ajouter un contrôleur de résultats, ajouter searchBar à la barre de navigation et gérer la sélection de l'utilisateur :

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

Ajouter une barre de recherche en haut d'une vue

L'exemple de code suivant montre comment ajouter searchBar en haut d'une vue.

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

Par défaut, UISearchController masque la barre de navigation lors de la présentation (cette option peut être désactivée). Dans les cas où la barre de navigation est visible et opaque, UISearchController ne définit pas correctement l'emplacement.

Utilisez le code suivant pour contourner le problème :

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;

Ajouter une barre de recherche à l'aide des résultats de popover

L'exemple de code suivant montre comment placer une barre de recherche sur le côté droit de la barre de navigation et afficher les résultats dans un pop-up.

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

Utiliser une source de données de table

Si votre application dispose d'une interface utilisateur de texte de recherche personnalisée, vous pouvez utiliser la classe GMSAutocompleteTableDataSource pour gérer la vue de tableau affichant les résultats sur le contrôleur de vue.

Pour utiliser GMSAutocompleteTableDataSource comme source de données et délégué de UITableView dans un contrôleur de vue :

  1. Implémentez les protocoles GMSAutocompleteTableDataSourceDelegate et UISearchBarDelegate dans le contrôleur de vue.
  2. Créez une instance GMSAutocompleteTableDataSource et attribuez le contrôleur de vue en tant que propriété de délégué.
  3. Définissez GMSAutocompleteTableDataSource comme propriétés de source de données et de délégué de l'instance UITableView sur le contrôleur de vue.
  4. Dans le gestionnaire de l'entrée de texte de recherche, appelez sourceTextHasChanged sur GMSAutocompleteTableDataSource.
    1. Gérez la sélection de l'utilisateur dans la méthode déléguée didAutocompleteWithPlace.
  5. Fermez le contrôleur dans les méthodes de délégué didAutocompleteWithPlace, didFailAutocompleteWithError et wasCancelled.

L'exemple de code suivant montre comment utiliser la classe GMSAutocompleteTableDataSource pour gérer la vue de tableau d'un UIViewController lorsque le UISearchBar est ajouté séparément.

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

      

Personnaliser les couleurs du texte et de l'arrière-plan

Vous pouvez définir les couleurs de l'ensemble du texte et des arrière-plans dans le contrôle de l'UI de saisie semi-automatique pour que le widget corresponde plus précisément à l'aspect visuel de votre application. Pour définir les couleurs de la commande d'interface utilisateur, vous pouvez procéder de deux façons :

  • En utilisant le protocole UIAppearance iOS intégré pour styliser globalement les contrôles d'interface utilisateur lorsque cela est possible. Ces paramètres s'appliquent à de nombreux éléments de contrôle de l'UI, mais pas à tous.
  • En utilisant les méthodes du SDK sur les classes de widget pour définir des propriétés qui ne sont pas compatibles avec le protocole UIAppearance.

En général, votre application utilise une combinaison du protocole UIAppearance et des méthodes du SDK. Le diagramme suivant présente les éléments qui peuvent être stylisés :

Couleurs de la commande d&#39;interface utilisateur pour la saisie semi-automatique

Le tableau suivant liste tous les éléments de l'UI et indique comment chacun d'eux doit être stylisé (protocole UIAppearance ou méthode SDK).

Élément d'interface utilisateur Méthode Tout sur le style
Teinte de la barre de navigation (arrière-plan) Protocole UIAppearance Appelez setBarTintColor sur le proxy UINavigationBar.
Couleur de la barre de navigation (caret du texte de la barre de recherche et bouton "Annuler") Protocole UIAppearance Appelez setTintColor sur le proxy UINavigationBar.
Couleur du texte de la barre de recherche Protocole UIAppearance Définissez NSForegroundColorAttributeName dans searchBarTextAttributes.
Couleur de la barre de recherche N/A La barre de recherche est translucide et s'affiche sous la forme d'une version ombrée de la barre de navigation.
Couleur du texte de l'espace réservé de la barre de recherche (texte de recherche par défaut) Protocole UIAppearance Définissez NSForegroundColorAttributeName dans placeholderAttributes.
Texte principal (également appliqué au texte des erreurs et des messages) Méthode SDK Appelez primaryTextColor.
Mise en surbrillance du texte principal Méthode SDK Appelez primaryTextHighlightColor.
Texte secondaire Méthode SDK Appelez secondaryTextColor.
Texte de l'erreur et du message Méthode SDK Appelez primaryTextColor.
Arrière-plan des cellules du tableau Méthode SDK Appelez tableCellBackgroundColor.
Couleur du séparateur de cellules du tableau Méthode SDK Appelez tableCellSeparatorColor.
Bouton "Réessayer" Méthode SDK Appelez tintColor.
Indicateur d'activité (spinner de progression) Protocole UIAppearance Appelez setColor sur le proxy UIActivityIndicatorView.
Logo "Optimisé par Google", image de nuage triste N/A La version blanche ou grise est automatiquement sélectionnée en fonction du contraste de l'arrière-plan.
Icônes en forme de loupe et d'effacement dans le champ de texte de la barre de recherche N/A Pour le style, remplacez les images par défaut par des images de la couleur souhaitée.

Utiliser le protocole UIAppearance

Vous pouvez utiliser le protocole UIAppearance pour obtenir le proxy d'apparence d'un élément d'interface utilisateur donné, que vous pouvez ensuite utiliser pour définir la couleur de l'élément d'interface utilisateur. Lorsqu'une modification est apportée, toutes les instances d'un élément d'interface utilisateur donné sont affectées. Par exemple, l'exemple suivant modifie globalement la couleur du texte des classes UITextField en vert lorsqu'elles sont contenues dans un UISearchBar :

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

Pour en savoir plus sur la définition des valeurs de couleur, consultez la documentation de référence sur la classe UIColor.

Les extraits de code suivants montrent toutes les commandes de proxy que vous devez utiliser pour styliser tous les éléments du contrôle d'interface utilisateur de saisie semi-automatique en plein écran. Ajoutez ce code à la méthode didFinishLaunchingWithOptions dans 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;

Définir les propriétés de style des commandes de l'UI

Un sous-ensemble d'éléments de contrôle de l'interface utilisateur possède des propriétés qui ne sont pas affectées par le protocole UIAppearance et doivent donc être définies directement. L'exemple de code suivant montre comment définir des couleurs de premier plan et d'arrière-plan, et comment les appliquer à une instance de contrôle d'interface utilisateur nommée acController. Ajoutez ce code à la méthode onLaunchClicked dans 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;

Obtenir des prédictions de lieux de manière programmatique

Vous pouvez créer une UI de recherche personnalisée en remplacement de celle fournie par le widget d'autocomplete. Pour ce faire, votre application doit obtenir des prédictions de lieux de manière programmatique. Votre application peut obtenir une liste des noms de lieux et/ou des adresses prédits de l'une des manières suivantes :

Appel de GMSPlacesClient findAutocompletePredictionsFromQuery:

Pour obtenir la liste des noms et/ou adresses de lieux prédits, commencez par instancier GMSPlacesClient, puis appelez la méthode GMSPlacesClient findAutocompletePredictionsFromQuery: avec les paramètres suivants :

  • Chaîne autocompleteQuery contenant le texte saisi par l'utilisateur.
  • Un GMSAutocompleteSessionToken, qui permet d'identifier chaque session individuelle. Votre application doit transmettre le même jeton pour chaque appel de requête de saisie semi-automatique, puis transmettre ce jeton, ainsi qu'un ID de lieu, dans l'appel suivant à fetchPlacefromPlaceID: pour récupérer les détails du lieu sélectionné par l'utilisateur.
  • A GMSAutocompleteFilter to:
    • Limiter les résultats à une région spécifique
    • Limitez les résultats à un type de lieu spécifique.
    • Objet GMSPlaceLocationBias/Restriction biaisant les résultats vers une zone spécifique définie par des limites de latitude et de longitude.
  • Méthode de rappel pour gérer les prédictions renvoyées.

Les exemples de code ci-dessous montrent un appel à findAutocompletePredictionsFromQuery:.

Swift

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

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

placesClient?.findAutocompletePredictions(fromQuery: "cheesebu",

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

Objective-C

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

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

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

L'API appelle la méthode de rappel spécifiée, en transmettant un tableau d'objets GMSAutocompletePrediction.

Chaque objet GMSAutocompletePrediction contient les informations suivantes :

  • attributedFullText : texte complet de la prédiction, sous la forme d'un NSAttributedString. Par exemple, "Opéra de Sydney, Sydney, Nouvelle-Galles du Sud, Australie". Chaque plage de texte correspondant à l'entrée utilisateur possède un attribut, kGMSAutocompleteMatchAttribute. Vous pouvez utiliser cet attribut pour mettre en évidence le texte correspondant dans la requête de l'utilisateur, comme illustré ci-dessous.
  • placeID : ID du lieu prédit. Un ID de lieu est un identifiant textuel qui identifie un lieu de façon unique. Pour en savoir plus sur les ID de lieu, consultez la présentation des ID de lieu.
  • distanceMeters : distance en ligne droite entre le origin spécifié et la destination. Si la propriété origin n'est pas définie, aucune valeur de distance ne sera renvoyée.

L'exemple de code suivant montre comment mettre en gras les parties du résultat qui correspondent au texte de la requête de l'utilisateur à l'aide 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;
    

Utiliser le récupérateur

Si vous souhaitez créer votre propre contrôle de saisie semi-automatique à partir de zéro, vous pouvez utiliser GMSAutocompleteFetcher, qui encapsule la méthode autocompleteQuery sur GMSPlacesClient. Le récupérateur limite les requêtes et ne renvoie que les résultats du texte de recherche saisi le plus récemment. Il ne fournit aucun élément d'UI.

Pour implémenter GMSAutocompleteFetcher, procédez comme suit :

  1. Implémentez le protocole GMSAutocompleteFetcherDelegate.
  2. Créez un objet GMSAutocompleteFetcher.
  3. Appelez sourceTextHasChanged sur le récupérateur au fur et à mesure que l'utilisateur saisit du texte.
  4. Gérez les prédictions et les erreurs à l'aide des méthodes de protocole didAutcompleteWithPredictions et didFailAutocompleteWithError.

L'exemple de code suivant montre comment utiliser le récupérateur pour saisir les entrées utilisateur et afficher les correspondances de lieux dans une vue de texte. La fonctionnalité de sélection d'un lieu a été omise. FetcherSampleViewController dérive de UIViewController dans 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

Jetons de session

Les jetons de session regroupent les phases de requête et de sélection d'une recherche de saisie semi-automatique d'un utilisateur dans une session distincte à des fins de facturation. La session commence lorsque l'utilisateur commence à saisir une requête et se termine lorsqu'il sélectionne un lieu. Chaque session peut comporter plusieurs requêtes, suivies d'une sélection de lieu. Lorsque la session prend fin, le jeton n'est plus valide. Votre application doit générer un nouveau jeton pour chaque session. Nous vous recommandons d'utiliser des jetons de session pour toutes les sessions de saisie semi-automatique programmatiques (lorsque vous utilisez le contrôleur plein écran ou le contrôleur de résultats, l'API s'en charge automatiquement).

Le SDK Places pour iOS utilise un GMSAutocompleteSessionToken pour identifier chaque session. Votre application doit transmettre un nouveau jeton de session au début de chaque nouvelle session, puis transmettre ce même jeton, ainsi qu'un ID de lieu, dans l'appel suivant à fetchPlacefromPlaceID: pour récupérer les détails du lieu sélectionné par l'utilisateur.

En savoir plus sur les jetons de session

Utilisez le code suivant pour générer un jeton de session :

let token: GMSAutocompleteSessionToken = GMSAutocompleteSessionToken.init()

Limites d'utilisation

Afficher les attributions dans votre application

  • Si votre application utilise le service de saisie semi-automatique par programmation, votre UI doit afficher une attribution "Optimisé par Google" ou apparaître dans une carte portant la marque Google.
  • Si votre application utilise le contrôle d'interface utilisateur de saisie semi-automatique, aucune action supplémentaire n'est requise (l'attribution requise est affichée par défaut).
  • Si vous récupérez et affichez des informations supplémentaires sur un lieu après avoir obtenu un lieu par ID, vous devez également afficher les attributions tierces.

Pour en savoir plus, consultez la documentation sur les attributions.

Contrôler l'indicateur d'activité réseau

Pour contrôler l'indicateur d'activité réseau dans la barre d'état des applications, vous devez implémenter les méthodes de délégué facultatives appropriées pour la classe d'autocomplétion que vous utilisez, puis activer et désactiver vous-même l'indicateur réseau.

  • Pour GMSAutocompleteViewController, vous devez implémenter les méthodes déléguées didRequestAutocompletePredictions: et didUpdateAutocompletePredictions:.
  • Pour GMSAutocompleteResultsViewController, vous devez implémenter les méthodes déléguées didRequestAutocompletePredictionsForResultsController: et didUpdateAutocompletePredictionsForResultsController:.
  • Pour GMSAutocompleteTableDataSource, vous devez implémenter les méthodes déléguées didRequestAutocompletePredictionsForTableDataSource: et didUpdateAutocompletePredictionsForTableDataSource:.

En implémentant ces méthodes et en définissant [UIApplication sharedApplication].networkActivityIndicatorVisible sur YES et NO respectivement, la barre d'état correspondra correctement à l'UI d'autocomplétion.

Limiter les résultats de saisie semi-automatique

Vous pouvez définir la commande d'interface utilisateur pour la saisie semi-automatique afin de limiter les résultats à une région géographique spécifique et/ou de les filtrer selon un ou plusieurs types de lieux, ou selon un ou plusieurs pays spécifiques. Pour limiter les résultats, vous pouvez procéder comme suit :

  • Pour privilégier (biaiser) les résultats dans la région définie, définissez locationBias sur GMSAutocompleteFilter (certains résultats en dehors de la région définie peuvent toujours être renvoyés). Si locationRestriction est également défini, locationBias sera ignoré.
  • Pour n'afficher que (restreindre) les résultats dans la région définie, définissez locationRestriction sur GMSAutocompleteFilter (seuls les résultats dans la région définie seront renvoyés).

    • Remarque : Cette restriction n'est appliquée qu'à des itinéraires complets. Des résultats synthétiques externes aux limites rectangulaires peuvent être renvoyés s'ils correspondent à un itinéraire qui chevauche la zone concernée.
  • Pour ne renvoyer que les résultats correspondant à un type de lieu particulier, définissez types sur GMSAutocompleteFilter (par exemple, si vous spécifiez TypeFilter.ADDRESS, le widget ne renverra que les résultats associés à une adresse précise).

  • Pour ne renvoyer que les résultats dans un maximum de cinq pays spécifiés, définissez countries sur GMSAutocompleteFilter.

Limiter les résultats à une région spécifique

Pour privilégier (biaiser) les résultats dans la région définie, définissez locationBias sur GMSAutocompleteFilter, comme indiqué ici :

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

Limiter les résultats à une région spécifique

Pour n'afficher que (restreindre) les résultats dans la région définie, définissez locationRestriction sur GMSAutocompleteFilter, comme indiqué ici :

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

Filtrer les résultats par pays

Pour filtrer les résultats dans un maximum de cinq pays spécifiés, définissez countries sur GMSAutocompleteFilter, comme indiqué ci-dessous :

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

Filtrer les résultats par type de lieu ou type de collection

Pour limiter les résultats à un certain type ou une certaine collection de types, définissez la propriété types de GMSAutoCompleteFilter. Utilisez cette propriété pour spécifier les filtres listés dans les tableaux 1, 2 et 3 de Types de lieux. Si aucun paramètre n'est spécifié, tous les types sont renvoyés.

Pour spécifier un filtre de type ou de collection de types :

  • Utilisez la propriété types pour spécifier jusqu'à cinq valeurs type issues des tableaux 1 et 2 de la page Types de lieux. Les valeurs de type sont définies par les constantes de GMSPlaceType.

  • Utilisez la propriété types pour spécifier une collection de types à partir du tableau 3 affiché sur la page Types de lieux. Les valeurs de la collection de types sont définies par les constantes de GMSPlaceType.

    Un seul type du Tableau 3 est autorisé dans la requête. Si vous spécifiez une valeur du Tableau 3, vous ne pouvez pas spécifier de valeur du Tableau 1 ni du Tableau 2. Si vous le faites, une erreur se produit.

Par exemple, pour ne renvoyer que les résultats correspondant à un type de lieu particulier, définissez types sur GMSAutocompleteFilter. L'exemple suivant montre comment définir le filtre pour ne renvoyer que les résultats avec une adresse précise :

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

Optimisation de Place Autocomplete (ancienne version)

Cette section décrit les bonnes pratiques pour vous aider à exploiter au mieux le service Place Autocomplete (ancienne version).

Voici quelques consignes générales :

  • Le moyen le plus rapide de développer une interface utilisateur fonctionnelle consiste à utiliser le widget Place Autocomplete (Legacy) de l'API Maps JavaScript, le widget Place Autocomplete (Legacy) du SDK Places pour Android ou la commande d'interface utilisateur Place Autocomplete (Legacy) du SDK Places pour iOS.
  • Développez dès le départ vos connaissances des champs de données Place Autocomplete (ancienne version) essentiels.
  • Les champs de pondération et de restriction de lieu sont facultatifs, mais peuvent avoir un impact important sur les performances de la saisie semi-automatique.
  • Utilisez la gestion des erreurs pour vérifier que votre application se dégrade correctement si l'API renvoie une erreur.
  • Assurez-vous que votre application fonctionne lorsqu'il n'y a aucune sélection et qu'elle propose aux utilisateurs un moyen de poursuivre.

Bonnes pratiques liées à l'optimisation des coûts

Optimisation de base des coûts

Pour optimiser le coût d'utilisation du service Place Autocomplete (Legacy), utilisez des masques de champ dans les widgets Place Details (Legacy) et Place Autocomplete (Legacy) afin de ne renvoyer que les champs de données de lieu dont vous avez besoin.

Optimisation avancée des coûts

Envisagez d'implémenter Place Autocomplete (ancienne version) de manière programmatique pour accéder au tarif par requête et demander des résultats d'API Geocoding pour le lieu sélectionné plutôt que pour Place Details (ancienne version). La tarification par requête associée à l'API Geocoding est plus rentable que la tarification par session (basée sur la session) si les deux conditions suivantes sont remplies :

  • Si vous n'avez besoin que de la latitude/longitude ou de l'adresse du lieu sélectionné par l'utilisateur, l'API Geocoding fournit ces informations à un prix inférieur à celui d'un appel Place Details (Legacy).
  • Si les utilisateurs sélectionnent une prédiction de saisie semi-automatique toutes les quatre requêtes de prédiction Place Autocomplete (ancienne version) ou moins en moyenne, la tarification par requête peut être plus rentable que celle par session.
Pour obtenir de l'aide concernant l'implémentation de Place Autocomplete (ancienne version) selon vos besoins, sélectionnez l'onglet correspondant à votre réponse à la question suivante.

Votre application nécessite-t-elle des informations autres que l'adresse et la latitude/longitude de la prédiction sélectionnée ?

Oui, j'ai besoin de plus d'informations

Utilisez Place Autocomplete (ancien) basé sur des sessions avec Place Details (ancien).
Étant donné que votre application nécessite des détails sur les lieux (ancienne version), tels que le nom du lieu, l'état de l'établissement ou les horaires d'ouverture, votre implémentation de Places Autocomplete (ancienne version) doit utiliser un jeton de session (de manière programmatique ou intégré aux widgets JavaScript, Android ou iOS). par session, plus les codes SKU de données Places applicables en fonction des champs de données de lieu que vous demandez.1

Implémentation de widgets
La gestion de sessions est automatiquement intégrée aux widgets JavaScript, Android ou iOS. Cela inclut les requêtes Place Autocomplete (ancienne version) et la requête Places Details (ancienne version) pour la prédiction sélectionnée. Veillez à spécifier le paramètre fields pour vous assurer de ne demander que les champs de données de lieu dont vous avez besoin.

Implémentation programmatique
Utilisez un jeton de session avec vos requêtes Place Autocomplete (ancienne version). Lorsque vous demandez des détails sur un lieu (ancienne version) concernant la prédiction sélectionnée, incluez les paramètres suivants :

  1. ID de lieu figurant dans la réponse Place Autocomplete (Legacy)
  2. Jeton de session utilisé dans la requête Place Autocomplete (ancienne version)
  3. Le paramètre fields spécifiant les champs de données de lieu dont vous avez besoin

Non, seuls les adresses et les lieux sont nécessaires

L'API Geocoding peut être une option plus rentable que Place Details (ancienne version) pour votre application, en fonction de vos performances d'utilisation de Place Autocomplete (ancienne version). L'efficacité de Place Autocomplete (ancienne version) varie d'une application à l'autre en fonction des informations saisies, du lieu d'utilisation de l'application et de l'implémentation des bonnes pratiques d'optimisation des performances.

Afin de répondre à la question suivante, analysez le nombre moyen de caractères saisis par un utilisateur avant qu'il sélectionne une prédiction Place Autocomplete (ancienne version) dans votre application.

En moyenne, vos utilisateurs sélectionnent-ils une prédiction Place Autocomplete (ancienne version) en quatre requêtes ou moins ?

Oui

Implémentez Place Autocomplete (ancienne version) de manière programmatique sans jeton de session, puis appelez l'API Geocoding sur la prédiction de lieu sélectionnée.
L'API Geocoding fournit des adresses et des coordonnées de latitude/longitude. Le coût de quatre requêtes Place Autocomplete (Legacy) – Par requête plus un appel de l'API Geocoding pour la prédiction de lieu sélectionnée est inférieur au coût par session de Place Autocomplete (Legacy)1.

Pensez à appliquer les bonnes pratiques liées aux performances pour aider vos utilisateurs à obtenir la prédiction qu'ils recherchent en utilisant moins de caractères.

Non

Utilisez Place Autocomplete (ancien) basé sur des sessions avec Place Details (ancien).
Étant donné que le nombre moyen de requêtes que vous prévoyez d'envoyer avant qu'un utilisateur ne sélectionne une prédiction Place Autocomplete (Legacy) dépasse le coût de la tarification par session, votre implémentation de Place Autocomplete (Legacy) doit utiliser un jeton de session pour les requêtes Place Autocomplete (Legacy) et la requête Place Details (Legacy) associée par session.1

Implémentation de widgets
La gestion de sessions est automatiquement intégrée aux widgets JavaScript, Android ou iOS. Cela inclut les requêtes Place Autocomplete (ancienne version) et la requête Places Details (ancienne version) pour la prédiction sélectionnée. Veillez à spécifier le paramètre fields afin de vous assurer de ne demander que les champs Données de base.

Implémentation programmatique
Utilisez un jeton de session avec vos requêtes Place Autocomplete (ancienne version). Lorsque vous demandez des détails sur un lieu (ancienne version) concernant la prédiction sélectionnée, incluez les paramètres suivants :

  1. ID de lieu figurant dans la réponse Place Autocomplete (Legacy)
  2. Jeton de session utilisé dans la requête Place Autocomplete (ancienne version)
  3. Paramètre fields spécifiant les champs de données de base comme l'adresse et la géométrie

Envisagez de reporter les requêtes Place Autocomplete (Legacy)
Vous pouvez appliquer des stratégies telles que le report d'une requête Place Autocomplete (Legacy) jusqu'à ce que l'utilisateur ait saisi les trois ou quatre premiers caractères. Votre application enverra ainsi moins de requêtes. Par exemple, si vous effectuez des requêtes Place Autocomplete (ancienne version) pour chaque caractère après le troisième caractère saisi par l'utilisateur, cela signifie que si l'utilisateur saisit sept caractères, puis sélectionne une prédiction pour laquelle vous effectuez une requête API Geocoding, le coût total correspondra à quatre requêtes Place Autocomplete (ancienne version) par requête + une requête Geocoding.1

Si, à cause du report de requêtes, votre requête programmatique moyenne est inférieure à quatre, vous pouvez suivre les instructions pour implémenter efficacement Place Autocomplete (ancienne version) avec l'API Geocoding. Notez que les requêtes reportées peuvent être perçues comme de la latence par l'utilisateur, qui peut s'attendre à voir des prédictions à chaque nouvelle frappe.

Pensez à appliquer les bonnes pratiques liées aux performances pour aider vos utilisateurs à obtenir la prédiction qu'ils recherchent en utilisant moins de caractères.


  1. Pour connaître les coûts, consultez les listes de prix de Google Maps Platform.

Bonnes pratiques en matière de performances

Les consignes suivantes décrivent les méthodes permettant d'optimiser les performances de Place Autocomplete (ancienne version) :

  • Ajoutez des restrictions locales, une pondération géographique et des préférences linguistiques (pour les implémentations programmatiques) à votre implémentation Place Autocomplete (ancienne version). La préférence linguistique n'est pas obligatoire pour les widgets, car ils sélectionnent cette option dans le navigateur ou l'appareil mobile de l'utilisateur.
  • Si Place Autocomplete (ancienne version) est accompagné d'une carte, vous pouvez pondérer la position en fonction de la fenêtre d'affichage de la carte.
  • Dans les cas où l'utilisateur ne choisit pas l'une des prédictions Place Autocomplete (Legacy), généralement parce qu'aucune d'entre elles n'est l'adresse souhaitée, vous pouvez réutiliser l'entrée utilisateur d'origine pour essayer d'obtenir des résultats plus pertinents :
    • Si vous pensez que l'utilisateur ne saisira que des informations d'adresse, réutilisez son entrée d'origine dans un appel à l'API Geocoding.
    • Si vous pensez que l'utilisateur saisira des requêtes pour un lieu spécifique avec un nom ou une adresse, utilisez une requête Find Place (ancienne). Si les résultats ne sont attendus que dans une région spécifique, utilisez la pondération géographique.
    Voici d'autres scénarios dans lesquels il est préférable de revenir à l'API Geocoding :
    • Les utilisateurs saisissent des adresses de sous-lieux, comme des adresses d'unités ou d'appartements spécifiques dans un bâtiment. Par exemple, l'adresse tchèque "Stroupežnického 3191/17, Praha" génère une prédiction partielle dans Place Autocomplete (Legacy).
    • Lorsque des utilisateurs saisissent des adresses qui contiennent un préfixe identifiant une portion de route, par exemple "23-30 29th St, Queens" à New York ou "47-380 Kamehameha Hwy, Kaneohe" sur l'île de Kauai, à Hawaï.

Dépannage

Bien qu'une grande variété d'erreurs puisse se produire, la majorité de celles que votre application est susceptible de rencontrer sont généralement dues à des erreurs de configuration (par exemple, une clé API incorrecte a été utilisée ou la clé API a été configurée de manière incorrecte) ou à des erreurs de quota (votre application a dépassé son quota). Pour en savoir plus sur les quotas, consultez Limites d'utilisation.

Les erreurs qui se produisent lors de l'utilisation des commandes de saisie semi-automatique sont renvoyées dans la méthode didFailAutocompleteWithError() des différents protocoles de délégué. La propriété code de l'objet NSError fourni est définie sur l'une des valeurs de l'énumération GMSPlacesErrorCode.