Autouzupełnianie miejsc

usługa autouzupełniania w pakiecie SDK Miejsc na iOS zwraca prognozy miejsc w odpowiedzi na zapytania użytkownika. Gdy użytkownik wpisuje tekst, usługa autouzupełniania zwraca sugestie dotyczące miejsc, takich jak firmy, adresy, kody plus i ciekawe miejsca.

Funkcję autouzupełniania możesz dodać do aplikacji na te sposoby:

Dodawanie elementu sterującego autouzupełniania

Element sterujący autouzupełniania to okno wyszukiwania z wbudowaną funkcją autouzupełniania. Gdy użytkownik wpisuje wyszukiwane hasła, komponent wyświetla listę przewidywanych miejsc do wyboru. Gdy użytkownik dokona wyboru, zwracana jest instancja GMSPlace, której aplikacja może użyć do uzyskania szczegółowych informacji o wybranym miejscu.

Element sterujący interfejsu autouzupełniania możesz dodać do aplikacji w ten sposób:

Dodawanie elementu sterującego trybem pełnoekranowym

Używaj elementu sterującego pełnym ekranem, gdy chcesz mieć kontekst modalny, w którym interfejs autouzupełniania tymczasowo zastępuje interfejs aplikacji, dopóki użytkownik nie dokona wyboru. Ta funkcja jest dostępna w klasie GMSAutocompleteViewController. Gdy użytkownik wybierze miejsce, Twoja aplikacja otrzyma wywołanie zwrotne.

Aby dodać do aplikacji kontrolkę pełnego ekranu:

  1. Utwórz w głównej aplikacji element interfejsu, który będzie uruchamiać element sterujący autouzupełniania, np. moduł obsługi dotyku na elemencie UIButton.
  2. Zaimplementuj protokół GMSAutocompleteViewControllerDelegate w kontrolerze widoku nadrzędnego.
  3. Utwórz instancję GMSAutocompleteViewController i przypisz nadrzędny kontroler widoku jako właściwość delegata.
  4. Utwórz GMSPlaceField, aby zdefiniować typy danych o miejscach, które mają być zwracane.
  5. Dodaj GMSAutocompleteFilter, aby ograniczyć zapytanie do określonego typu miejsca.
  6. Wyświetl GMSAutocompleteViewController za pomocą [self presentViewController...].
  7. Obsłuż wybór użytkownika w metodzie didAutocompleteWithPlace delegate.
  8. Odrzuć kontroler w metodach delegowania didAutocompleteWithPlace, didFailAutocompleteWithErrorwasCancelled.

Ten przykład pokazuje jeden z możliwych sposobów uruchomieniaGMSAutocompleteViewController w odpowiedzi na naciśnięcie przycisku przez użytkownika.

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

Dodawanie kontrolera wyników

Użyj kontrolera wyników, jeśli chcesz mieć większą kontrolę nad interfejsem wprowadzania tekstu. Kontroler wyników dynamicznie przełącza widoczność listy wyników na podstawie fokusu interfejsu użytkownika.

Aby dodać do aplikacji kontroler wyników:

  1. Utwórz GMSAutocompleteResultsViewController.
    1. Zaimplementuj protokół GMSAutocompleteResultsViewControllerDelegate w kontrolerze widoku nadrzędnego i przypisz go jako właściwość delegata.
  2. Utwórz obiekt UISearchController, przekazując GMSAutocompleteResultsViewController jako argument kontrolera wyników.
  3. Ustaw wartość GMSAutocompleteResultsViewController jako właściwość searchResultsUpdater elementu UISearchController.
  4. Dodaj searchBar dla UISearchController do interfejsu aplikacji.
  5. Obsłuż wybór użytkownika w metodzie didAutocompleteWithPlace delegate.

Pasek wyszukiwania UISearchController możesz umieścić w interfejsie aplikacji na kilka sposobów:

Dodawanie paska wyszukiwania do paska nawigacyjnego

Ten przykładowy kod ilustruje dodawanie kontrolera wyników, dodawanie elementu searchBar na pasku nawigacyjnym oraz obsługę wyboru użytkownika:

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

Dodawanie paska wyszukiwania u góry widoku

Poniższy przykład kodu pokazuje dodawanie elementu searchBar u góry widoku.

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

DomyślnieUISearchController ukrywa pasek nawigacyjny podczas prezentacji (można to wyłączyć). W przypadku, gdy pasek nawigacyjny jest widoczny i nieprzezroczysty, UISearchController nie ustawia prawidłowo miejsca docelowego.

Użyj tego kodu jako obejścia:

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;

Dodawanie paska wyszukiwania za pomocą wyników wyskakujących

Ten przykładowy kod pokazuje umieszczanie paska wyszukiwania po prawej stronie paska nawigacyjnego i wyświetlanie wyników w wyskakującym okienku.

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

Korzystanie ze źródła danych tabeli

Jeśli Twoja aplikacja ma niestandardowy interfejs tekstu wyszukiwania, możesz użyć klasy GMSAutocompleteTableDataSource do sterowania widokiem tabeli wyświetlającym wyniki w kontrolerze widoku.

Aby użyć GMSAutocompleteTableDataSource jako źródła danych i delegata UITableView w kontrolerze widoku:

  1. Zaimplementuj protokoły GMSAutocompleteTableDataSourceDelegateUISearchBarDelegate w kontrolerze widoku.
  2. Utwórz instancję GMSAutocompleteTableDataSource i przypisz kontroler widoku jako właściwość delegata.
  3. Ustaw GMSAutocompleteTableDataSource jako źródło danych i przekaż właściwości instancji UITableView w kontrolerze widoku.
  4. W funkcji obsługi danych wejściowych tekstu wyszukiwania wywołaj sourceTextHasChanged na elemencie GMSAutocompleteTableDataSource.
    1. Obsłuż wybór użytkownika w metodzie didAutocompleteWithPlace delegate.
  5. Odrzuć kontroler w metodach delegata didAutocompleteWithPlace, didFailAutocompleteWithError, wasCancelled.

Poniższy przykład kodu pokazuje, jak używać klasy GMSAutocompleteTableDataSource do wyświetlania tabeli UIViewController, gdy element UISearchBar jest dodawany osobno.

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

      

Dostosowywanie kolorów tekstu i tła

Możesz ustawić kolory tekstu i tła w interfejsie autouzupełniania, aby widżet lepiej pasował do wyglądu aplikacji. Kolory elementów interfejsu możesz ustawić na 2 sposoby:

  • Korzystając z wbudowanego protokołu UIAppearance w iOS, aby w miarę możliwości globalnie określać styl elementów sterujących interfejsu. Te ustawienia mają zastosowanie do wielu, ale nie wszystkich elementów interfejsu.
  • Używając metod pakietu SDK w klasach widżetów do ustawiania właściwości, które nie są obsługiwane przez protokół UIAppearance.

Zwykle aplikacja korzysta z kombinacji protokołu UIAppearance i metod pakietu SDK. Ten diagram pokazuje, które elementy można stylizować:

Kolory elementu sterującego autouzupełniania

W tabeli poniżej znajdziesz wszystkie elementy interfejsu i informacje o tym, jak należy je stylować (protokół UIAppearance lub metoda pakietu SDK).

Element interfejsu Metoda Poradniki i styl
Odcień paska nawigacyjnego (tło) Protokół UIAppearance Zadzwoń pod numer UINavigationBar, którego używa setBarTintColor.
Kolor paska nawigacyjnego (karetka tekstu na pasku wyszukiwania i przycisk Anuluj) Protokół UIAppearance Zadzwoń pod numer UINavigationBar, którego używa setTintColor.
Kolor tekstu na pasku wyszukiwania Protokół UIAppearance Ustaw NSForegroundColorAttributeNamesearchBarTextAttributes.
Kolor odcienia paska wyszukiwania Nie dotyczy Pasek wyszukiwania jest półprzezroczysty i wyświetla się jako zacieniona wersja paska nawigacyjnego.
Kolor tekstu zastępczego na pasku wyszukiwania (domyślny tekst wyszukiwania) Protokół UIAppearance Ustaw NSForegroundColorAttributeNameplaceholderAttributes.
Tekst podstawowy (dotyczy też tekstu błędu i wiadomości) Metoda SDK Zadzwoń do firmy primaryTextColor.
Wyróżnienie tekstu głównego Metoda SDK Zadzwoń do firmy primaryTextHighlightColor.
Tekst dodatkowy Metoda SDK Zadzwoń do firmy secondaryTextColor.
Błąd i tekst komunikatu Metoda SDK Zadzwoń do firmy primaryTextColor.
Tło komórki tabeli Metoda SDK Zadzwoń do firmy tableCellBackgroundColor.
Kolor separatora komórki tabeli Metoda SDK Zadzwoń do firmy tableCellSeparatorColor.
Przycisk „Spróbuj ponownie” Metoda SDK Zadzwoń do firmy tintColor.
Wskaźnik aktywności (spinner postępu) Protokół UIAppearance Zadzwoń pod numer UIActivityIndicatorView, którego używa setColor.
Logo „Powered by Google”, smutna chmura Nie dotyczy Biała lub szara wersja jest wybierana automatycznie na podstawie kontrastu tła.
Ikony lupy i czyszczenia tekstu w polu tekstowym paska wyszukiwania Nie dotyczy Aby dostosować styl, zastąp domyślne obrazy obrazami w wybranym kolorze.

Korzystanie z protokołu UIAppearance

Możesz użyć protokołu UIAppearance, aby uzyskać proxy wyglądu danego elementu interfejsu, którego możesz następnie użyć do ustawienia koloru tego elementu. Gdy wprowadzisz zmianę, będzie ona miała wpływ na wszystkie wystąpienia danego elementu interfejsu. Na przykład poniższy kod globalnie zmienia kolor tekstu klas UITextField na zielony, gdy znajdują się one w elemencie UISearchBar:

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

Więcej informacji o określaniu wartości kolorów znajdziesz w dokumentacji klasy UIColor.

Poniższe fragmenty kodu pokazują wszystkie polecenia proxy, których musisz użyć, aby dostosować styl wszystkich elementów w kontrolce interfejsu autouzupełniania na pełnym ekranie. Dodaj ten kod do metody didFinishLaunchingWithOptions w pliku 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;

Ustawianie właściwości stylu elementu sterującego interfejsu

Podzbiór elementów sterujących interfejsu ma właściwości, na które nie ma wpływu protokół UIAppearance, więc muszą być ustawiane bezpośrednio. Poniższy przykład kodu pokazuje, jak zdefiniować kolory pierwszego planu i tła oraz zastosować je do instancji elementu interfejsu o nazwie acController. Dodaj ten kod do metody onLaunchClicked w pliku 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;

Uzyskiwanie prognoz dotyczących miejsc w sposób zautomatyzowany

Możesz utworzyć niestandardowy interfejs wyszukiwania jako alternatywę dla interfejsu udostępnianego przez widżet autouzupełniania. Aby to zrobić, aplikacja musi uzyskiwać prognozy miejsc programowo. Aplikacja może uzyskać listę przewidywanych nazw miejsc lub adresów na jeden z tych sposobów:

Dzwonię do: GMSPlacesClient findAutocompletePredictionsFromQuery:

Aby uzyskać listę przewidywanych nazw miejsc lub adresów, najpierw utwórz instancję GMSPlacesClient, a potem wywołaj metodę GMSPlacesClient findAutocompletePredictionsFromQuery: z tymi parametrami:

  • Ciąg autocompleteQuery zawierający tekst wpisany przez użytkownika.
  • A GMSAutocompleteSessionToken, który służy do identyfikowania poszczególnych sesji. Aplikacja powinna przekazywać ten sam token w każdym wywołaniu żądania autouzupełniania, a następnie przekazywać ten token wraz z identyfikatorem miejsca w kolejnym wywołaniu interfejsu fetchPlacefromPlaceID:, aby pobrać szczegóły miejsca wybranego przez użytkownika.
  • A GMSAutocompleteFilter to:
    • faworyzować wyniki z określonego regionu lub ograniczać się do nich;
    • Ogranicz wyniki do określonego typu miejsca.
    • Obiekt GMSPlaceLocationBias/Restriction, który wpływa na wyniki, aby były bardziej dopasowane do określonego obszaru wyznaczonego przez granice szerokości i długości geograficznej.
  • Metoda wywołania zwrotnego do obsługi zwróconych prognoz.

Przykłady kodu poniżej pokazują wywołanie funkcji 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);
    }
  }
}];

Interfejs API wywołuje określoną metodę wywołania zwrotnego, przekazując tablicę obiektów GMSAutocompletePrediction.

Każdy obiekt GMSAutocompletePrediction zawiera te informacje:

  • attributedFullText – pełny tekst prognozy w formie NSAttributedString. Na przykład „Sydney Opera House, Sydney, New South Wales, Australia”. Każdy zakres tekstu pasujący do danych wejściowych użytkownika ma atrybut kGMSAutocompleteMatchAttribute. Możesz użyć tego atrybutu, aby wyróżnić pasujący tekst w zapytaniu użytkownika, np. jak pokazano poniżej.
  • placeID – identyfikator miejsca prognozowanego. Identyfikator miejsca to identyfikator tekstowy, który jednoznacznie identyfikuje miejsce. Więcej informacji o identyfikatorach miejsc znajdziesz w omówieniu identyfikatorów miejsc.
  • distanceMeters – odległość w linii prostej od określonego punktu origin do miejsca docelowego. Jeśli właściwość origin nie jest ustawiona, nie zostanie zwrócona żadna wartość odległości.

Poniższy przykład kodu pokazuje, jak za pomocą tagu enumerateAttribute wyróżnić pogrubionym tekstem części wyniku, które pasują do tekstu w zapytaniu użytkownika:

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;
    

Korzystanie z narzędzia do pobierania

Jeśli chcesz od podstaw utworzyć własny element sterujący autouzupełniania, możesz użyć elementu GMSAutocompleteFetcher, który opakowuje metodę autocompleteQueryGMSPlacesClient. Pobieranie ogranicza liczbę żądań, zwracając tylko wyniki dla ostatnio wpisanego tekstu wyszukiwania. Nie zawiera elementów interfejsu.

Aby wdrożyć GMSAutocompleteFetcher, wykonaj te czynności:

  1. Zaimplementuj protokół GMSAutocompleteFetcherDelegate.
  2. Utwórz obiekt GMSAutocompleteFetcher.
  3. Wywołaj funkcję sourceTextHasChanged w wyszukiwarce, gdy użytkownik wpisuje tekst.
  4. Obsługuj prognozy i błędy za pomocą metod protokołu didAutcompleteWithPredictionsdidFailAutocompleteWithError.

Poniższy przykład kodu pokazuje, jak za pomocą narzędzia do pobierania danych przyjmować dane wejściowe od użytkownika i wyświetlać pasujące miejsca w widoku tekstowym. Funkcja wyboru miejsca została pominięta. FetcherSampleViewController pochodzi z UIViewController w pliku 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

Tokeny sesji

Tokeny sesji grupują fazy zapytania i wyboru autouzupełniania wyszukiwania użytkownika w osobną sesję na potrzeby rozliczeń. Sesja rozpoczyna się, gdy użytkownik zaczyna wpisywać zapytanie, a kończy, gdy wybierze miejsce. Każda sesja może zawierać wiele zapytań, po których następuje wybór jednego miejsca. Po zakończeniu sesji token traci ważność. Aplikacja musi generować nowy token dla każdej sesji. W przypadku wszystkich sesji autouzupełniania w ramach automatyzacji (gdy używasz kontrolera pełnego ekranu lub kontrolera wyników, interfejs API automatycznie się tym zajmuje) zalecamy używanie tokenów sesji.

Pakiet SDK Miejsc na iOS używa GMSAutocompleteSessionToken do identyfikowania każdej sesji. Aplikacja powinna przekazywać nowy token sesji na początku każdej nowej sesji, a następnie przekazywać ten sam token wraz z identyfikatorem miejsca w kolejnym wywołaniu funkcji fetchPlacefromPlaceID:, aby pobrać szczegóły miejsca wybranego przez użytkownika.

Więcej informacji o tokenach sesji

Aby wygenerować nowy token sesji, użyj tego kodu:

let token: GMSAutocompleteSessionToken = GMSAutocompleteSessionToken.init()

Limity wykorzystania

Wyświetlanie atrybucji w aplikacji

  • Jeśli Twoja aplikacja korzysta z usługi autouzupełniania programowo, interfejs musi wyświetlać atrybucję „Powered by Google” lub pojawiać się na mapie oznaczonej marką Google.
  • Jeśli Twoja aplikacja korzysta z elementu sterującego autouzupełniania, nie musisz podejmować żadnych dodatkowych działań (wymagane atrybucje są wyświetlane domyślnie).
  • Jeśli po pobraniu miejsca według identyfikatora pobierzesz i wyświetlisz dodatkowe informacje o miejscu, musisz też wyświetlić atrybucje pochodzące od innych firm.

Więcej informacji znajdziesz w dokumentacji dotyczącej atrybucji.

Sterowanie wskaźnikiem aktywności sieci

Aby kontrolować wskaźnik aktywności sieci na pasku stanu aplikacji, musisz zaimplementować odpowiednie opcjonalne metody delegowania dla używanej klasy autouzupełniania i samodzielnie włączać i wyłączać wskaźnik sieci.

  • W przypadku GMSAutocompleteViewController musisz zaimplementować metody delegowania didRequestAutocompletePredictions:didUpdateAutocompletePredictions:.
  • W przypadku GMSAutocompleteResultsViewController musisz zaimplementować metody delegowania didRequestAutocompletePredictionsForResultsController:didUpdateAutocompletePredictionsForResultsController:.
  • W przypadku GMSAutocompleteTableDataSource musisz zaimplementować metody delegowania didRequestAutocompletePredictionsForTableDataSource:didUpdateAutocompletePredictionsForTableDataSource:.

Wdrażając te metody i ustawiając odpowiednio [UIApplication sharedApplication].networkActivityIndicatorVisible na YESNO, pasek stanu będzie prawidłowo dopasowany do interfejsu autouzupełniania.

Ograniczanie wyników autouzupełniania

Możesz skonfigurować element sterujący autouzupełniania tak, aby ograniczał wyniki do określonego regionu geograficznego lub filtrował wyniki według jednego lub kilku typów miejsc albo według określonego kraju lub krajów. Aby ograniczyć wyniki, możesz wykonać te czynności:

  • Aby preferować (faworyzować) wyniki w określonym regionie, ustaw locationBias na GMSAutocompleteFilter (niektóre wyniki spoza określonego regionu mogą nadal być zwracane). Jeśli ustawiona jest też wartość locationRestriction, wartość locationBias zostanie zignorowana.
  • Aby wyświetlać tylko wyniki w określonym regionie (ograniczyć wyniki), ustaw wartość locationRestriction w parametrze GMSAutocompleteFilter (zostaną zwrócone tylko wyniki w określonym regionie).

    • Uwaga: to ograniczenie jest stosowane tylko do całych tras. Wyniki syntetyczne znajdujące się poza prostokątnymi granicami mogą być zwracane na podstawie trasy, która pokrywa się z ograniczeniem lokalizacji.
  • Aby zwracać tylko wyniki zgodne z określonym typem miejsca, ustaw typesGMSAutocompleteFilter (np. określenie TypeFilter.ADDRESS spowoduje, że widżet będzie zwracać tylko wyniki z dokładnym adresem).

  • Aby zwracać tylko wyniki z maksymalnie 5 określonych krajów, ustaw wartość countries w parametrze GMSAutocompleteFilter.

Przekazywanie wyników do określonego regionu

Aby preferować (faworyzować) wyniki w określonym regionie, ustaw locationBiasGMSAutocompleteFilter, jak pokazano tutaj:

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

Ograniczanie wyników do określonego regionu

Aby wyświetlać tylko wyniki w określonym regionie (ograniczyć je), ustaw wartość locationRestriction w parametrze GMSAutocompleteFilter, jak pokazano poniżej:

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

Filtrowanie wyników według kraju

Aby filtrować wyniki w maksymalnie 5 określonych krajach, ustaw countries na GMSAutocompleteFilter, jak pokazano tutaj:

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

Filtrowanie wyników według typu miejsca lub kolekcji typów

Ogranicz wyniki do określonego typu lub kolekcji typów, ustawiając właściwość types elementu GMSAutoCompleteFilter. Użyj tej właściwości, aby określić filtry wymienione w tabelach 1, 2 i 3 na stronie Rodzaje miejsc. Jeśli nic nie zostanie określone, zwracane są wszystkie typy.

Aby określić filtr typu lub kolekcji typów:

  • Użyj właściwości types, aby określić maksymalnie 5 wartości type z tabeli 1 i tabeli 2 na stronie Typy miejsc. Wartości typu są zdefiniowane przez stałe w GMSPlaceType.

  • Użyj właściwości types, aby określić kolekcję typów z tabeli 3, która jest widoczna na stronie Typy miejsc. Wartości kolekcji typu są zdefiniowane przez stałe w GMSPlaceType.

    W żądaniu dozwolony jest tylko jeden typ z tabeli 3. Jeśli określisz wartość z tabeli 3, nie możesz określić wartości z tabeli 1 ani 2. Jeśli to zrobisz, wystąpi błąd.

Aby na przykład zwrócić tylko wyniki zgodne z określonym typem miejsca, ustaw wartość types w parametrze GMSAutocompleteFilter. Przykład poniżej pokazuje ustawienie filtra tak, aby zwracał tylko wyniki z dokładnym adresem:

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

Optymalizacja autouzupełniania miejsc (starsza wersja)

W tej sekcji opisujemy sprawdzone metody, które pomogą Ci w pełni wykorzystać możliwości usługi Autouzupełnianie miejsc (starsza wersja).

Oto kilka ogólnych wskazówek:

  • Najszybszym sposobem na stworzenie działającego interfejsu użytkownika jest użycie widżetu autouzupełniania miejsc (starszego) z Maps JavaScript API, widżetu autouzupełniania miejsc (starszego) z pakietu SDK Miejsc na Androida lub elementu interfejsu autouzupełniania miejsc (starszego) z pakietu SDK Miejsc na iOS.
  • Od początku poznaj najważniejsze pola danych usługi Autouzupełnianie miejsc (starsza wersja).
  • Pola dotyczące preferowania lokalizacji i ograniczania lokalizacji są opcjonalne, ale mogą mieć znaczący wpływ na skuteczność autouzupełniania.
  • Używaj obsługi błędów, aby zapewnić prawidłowe działanie aplikacji, gdy interfejs API zwróci błąd.
  • Upewnij się, że aplikacja obsługuje sytuacje, w których nie ma wyboru, i oferuje użytkownikom możliwość kontynuowania.

Sprawdzone metody optymalizacji kosztów

Podstawowa optymalizacja kosztów

Aby zoptymalizować koszt korzystania z usługi autouzupełniania miejsc (starszej wersji), używaj masek pól w widżetach szczegółów miejsca (starszej wersji) i autouzupełniania miejsc (starszej wersji), aby zwracać tylko potrzebne pola z danymi o miejscach.

Zaawansowana optymalizacja kosztów

Rozważ programowe wdrożenie autouzupełniania miejsc (starszego), aby uzyskać dostęp do ceny za żądanie i zamiast szczegółów miejsca (starszego) wysyłać żądania wyników interfejsu Geocoding API dotyczących wybranego miejsca. Ceny za żądanie w połączeniu z interfejsem Geocoding API są bardziej opłacalne niż ceny za sesję (oparte na sesjach), jeśli spełnione są oba te warunki:

  • Jeśli potrzebujesz tylko szerokości i długości geograficznej lub adresu wybranego miejsca, interfejs Geocoding API dostarczy te informacje za mniejszą opłatą niż wywołanie interfejsu Place Details (starszego).
  • Jeśli użytkownicy wybierają prognozę autouzupełniania średnio w ramach 4 lub mniejszej liczby żądań prognoz autouzupełniania miejsc (starsza wersja), ceny za żądanie mogą być bardziej opłacalne niż ceny za sesję.
Aby uzyskać pomoc w wyborze implementacji Autouzupełniania miejsc (starszej wersji), która odpowiada Twoim potrzebom, wybierz kartę odpowiadającą Twojej odpowiedzi na to pytanie.

Czy Twoja aplikacja wymaga innych informacji niż adres i szerokość/długość geograficzna wybranej prognozy?

Tak, potrzebne są dodatkowe informacje

Używaj autouzupełniania miejsc opartego na sesji (starsza wersja) z informacjami o miejscu (starsza wersja).
Ponieważ Twoja aplikacja wymaga szczegółów miejsca (starsza wersja), takich jak nazwa miejsca, stan firmy lub godziny otwarcia, w implementacji autouzupełniania miejsc (starsza wersja) należy używać tokena sesji (programowo lub wbudowanego w widżety JavaScript, Android lub iOS). za sesję oraz odpowiednie SKU danych o miejscach w zależności od tego, o które pola danych o miejscach prosisz.1

Implementacja widżetu
Zarządzanie sesjami jest automatycznie wbudowane w widżety JavaScript, AndroidiOS. Obejmuje to zarówno żądania autouzupełniania miejsca (starsza wersja), jak i żądania szczegółów miejsca (starsza wersja) dotyczące wybranej prognozy. Pamiętaj, aby określić parametr fields, aby mieć pewność, że żądasz tylko potrzebnych pól z danymi o miejscach.

Implementacja programowa
W żądaniach autouzupełniania miejsc (starsza wersja) używaj tokena sesji. Gdy wysyłasz żądanie Szczegóły miejsca (starsza wersja) dotyczące wybranej prognozy, uwzględnij te parametry:

  1. Identyfikator miejsca z odpowiedzi Autouzupełniania miejsc (starsza wersja).
  2. Token sesji użyty w żądaniu autouzupełniania miejsc (starsza wersja).
  3. Parametr fields określający potrzebne pola danych o miejscach.

Nie, potrzebny jest tylko adres i lokalizacja

W zależności od wydajności korzystania z autouzupełniania miejsc (starszego) interfejs Geocoding API może być bardziej opłacalną opcją niż szczegóły miejsca (starsze) w Twojej aplikacji. Skuteczność każdej aplikacji korzystającej z usługi Autouzupełnianie miejsc (starsza wersja) zależy od tego, co wpisują użytkownicy, gdzie jest używana aplikacja i czy zostały wdrożone sprawdzone metody optymalizacji wydajności.

Aby odpowiedzieć na to pytanie, przeanalizuj, ile znaków użytkownik wpisuje średnio, zanim wybierze prognozę autouzupełniania miejsc (starsza wersja) w Twojej aplikacji.

Czy użytkownicy wybierają prognozę autouzupełniania miejsc (starsza wersja) średnio w 4 lub mniejszej liczbie żądań?

Tak

Zaimplementuj programowo funkcję autouzupełniania miejsca (starszą wersję) bez tokenów sesji i wywołaj interfejs Geocoding API w przypadku wybranego przewidywania miejsca.
Interfejs Geocoding API dostarcza adresy oraz współrzędne szerokości i długości geograficznej. Wysłanie 4 żądań Autouzupełnianie miejsc (starsza wersja) – za żądanie i wywołanie Geocoding API dotyczące wybranej prognozy miejsca jest tańsze niż koszt sesji w przypadku Autouzupełniania miejsc (starsza wersja) – za sesję.1

Aby użytkownicy mogli uzyskać prognozę, której szukają, przy użyciu jeszcze mniejszej liczby znaków, warto zastosować sprawdzone metody dotyczące wydajności.

Nie

Używaj autouzupełniania miejsc opartego na sesji (starsza wersja) z informacjami o miejscu (starsza wersja).
Średnia liczba żądań, które prawdopodobnie wyślesz, zanim użytkownik wybierze prognozę autouzupełniania miejsca (starsza wersja), przekracza koszt ceny za sesję, więc w implementacji autouzupełniania miejsca (starsza wersja) należy używać tokena sesji zarówno w przypadku żądań autouzupełniania miejsca (starsza wersja), jak i powiązanych żądań szczegółów miejsca (starsza wersja) na sesję.1

Implementacja widżetu
Zarządzanie sesjami jest automatycznie wbudowane w widżety JavaScript, AndroidiOS. Obejmuje to zarówno żądania autouzupełniania miejsca (starsza wersja), jak i żądania szczegółów miejsca (starsza wersja) dotyczące wybranej prognozy. Aby mieć pewność, że żądasz tylko pól danych podstawowych, określ parametr fields.

Implementacja programowa
W żądaniach autouzupełniania miejsc (starsza wersja) używaj tokena sesji. Gdy wysyłasz żądanie Szczegóły miejsca (starsza wersja) dotyczące wybranej prognozy, uwzględnij te parametry:

  1. Identyfikator miejsca z odpowiedzi Autouzupełniania miejsc (starsza wersja).
  2. Token sesji użyty w żądaniu autouzupełniania miejsc (starsza wersja).
  3. Parametr fields określający pola danych podstawowych, takie jak adres i geometria.

Rozważ opóźnienie żądań autouzupełniania miejsc (starsza wersja)
Możesz zastosować strategie, takie jak opóźnienie żądania autouzupełniania miejsc (starsza wersja) do momentu, gdy użytkownik wpisze pierwsze 3–4 znaki, aby aplikacja wysyłała mniej żądań. Jeśli na przykład wysyłasz żądania autouzupełniania miejsc (starszej wersji) dla każdego znaku po wpisaniu przez użytkownika trzeciego znaku, a użytkownik wpisze 7 znaków, a potem wybierze prognozę, dla której wysyłasz 1 żądanie do interfejsu Geocoding API, łączny koszt wyniesie 4 żądania autouzupełniania miejsc (starszej wersji) + geokodowanie.1

Jeśli opóźnienie żądań może spowodować, że średnia liczba żądań programowych będzie mniejsza niż 4, możesz postępować zgodnie z instrukcjami dotyczącymi implementacji wydajnego autouzupełniania miejsc (starszego) z interfejsem Geocoding API. Pamiętaj, że opóźnianie żądań może być postrzegane przez użytkownika jako opóźnienie, ponieważ może on oczekiwać, że prognozy będą wyświetlane po każdym naciśnięciu klawisza.

Aby ułatwić użytkownikom uzyskanie prognozy, której szukają, przy użyciu mniejszej liczby znaków, rozważ zastosowanie sprawdzonych metod dotyczących wydajności.


  1. Ceny znajdziesz w cennikach Google Maps Platform.

Sprawdzone metody dotyczące wydajności

Poniższe wytyczne opisują sposoby optymalizacji skuteczności interfejsu Place Autocomplete (starszego):

  • Dodaj do implementacji funkcji Autouzupełnianie miejsca (starsza wersja) ograniczenia dotyczące kraju, ustawianie preferencji lokalizacji i (w przypadku implementacji programowych) preferencje językowe. W przypadku widżetów nie trzeba określać preferencji językowych, ponieważ są one pobierane z przeglądarki lub urządzenia mobilnego użytkownika.
  • Jeśli usługa autouzupełniania miejsc (starsza wersja) jest używana z mapą, możesz określić lokalizację na podstawie widocznego obszaru mapy.
  • W sytuacjach, gdy użytkownik nie wybierze żadnej z prognoz autouzupełniania miejsca (starsza wersja), zwykle dlatego, że żadna z nich nie jest adresem, którego szuka, możesz ponownie użyć pierwotnego tekstu wpisanego przez użytkownika, aby uzyskać trafniejsze wyniki:
    • Jeśli oczekujesz, że użytkownik wpisze tylko informacje o adresie, użyj ponownie pierwotnych danych wejściowych użytkownika w wywołaniu interfejsu Geocoding API.
    • Jeśli oczekujesz, że użytkownik będzie wpisywać zapytania dotyczące konkretnego miejsca według nazwy lub adresu, użyj żądania Find Place (Legacy). Jeśli wyniki są oczekiwane tylko w określonym regionie, użyj ustawień lokalizacji.
    Inne scenariusze, w których warto wrócić do Geocoding API:
    • użytkownicy wpisujący adresy podrzędne, np. adresy konkretnych lokali lub mieszkań w budynku; Na przykład czeski adres „Stroupežnického 3191/17, Praha” generuje częściową podpowiedź w usłudze Autouzupełnianie miejsc (starsza wersja).
    • Użytkownicy wpisujący adresy z prefiksami odcinków dróg, np. „23–30 29th St, Queens” w Nowym Jorku lub „47–380 Kamehameha Hwy, Kaneohe” na wyspie Kauai na Hawajach.

Rozwiązywanie problemów

Może wystąpić wiele różnych błędów, ale większość z nich jest zwykle spowodowana błędami konfiguracji (np. użyto nieprawidłowego klucza interfejsu API lub klucz interfejsu API został nieprawidłowo skonfigurowany) lub błędami związanymi z limitem (aplikacja przekroczyła limit). Więcej informacji o limitach znajdziesz w sekcji Limity wykorzystania.

Błędy, które występują podczas korzystania z elementów sterujących autouzupełniania, są zwracane w metodzie didFailAutocompleteWithError() różnych protokołów delegowania. Właściwość code dostarczonego obiektu NSError jest ustawiona na jedną z wartości wyliczenia GMSPlacesErrorCode.