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 zwraca sugestie dotyczące miejsc, takich jak firmy, adresy, kody plus i ciekawe miejsca.

Autouzupełnianie 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 wpisze wyszukiwane hasło, element sterujący wyświetli listę przewidywanych miejsc do wyboru. Gdy użytkownik dokona wyboru, zwrócony zostanie obiekt GMSPlace, którego Twoja aplikacja może użyć do uzyskania szczegółowych informacji o wybranym miejscu.

Element sterujący autouzupełniania możesz dodać do aplikacji w następujący sposób:

Dodawanie elementu sterującego trybem pełnoekranowym

Użyj elementu sterującego pełnym ekranem, jeśli chcesz użyć kontekstu modalnego, w którym interfejs autouzupełniania tymczasowo zastąpi interfejs aplikacji, dopóki użytkownik nie dokona wyboru. Ta funkcja jest dostępna w ramach klasy GMSAutocompleteViewController. Gdy użytkownik wybierze miejsce, Twoja aplikacja otrzyma wywołanie zwrotne.

Aby dodać do aplikacji kontrolę na pełnym ekranie:

  1. Utwórz w aplikacji głównej element interfejsu użytkownika, który uruchamia element sterujący autouzupełniania, na przykład element obsługi dotyku na przycisku UIButton.
  2. W kontrolerze widoku nadrzędnego zastosuj protokół GMSAutocompleteViewControllerDelegate.
  3. Utwórz instancję GMSAutocompleteViewController i przypisz do niej nadrzędny kontroler widoku jako obiekt zastępczy.
  4. Utwórz plik GMSPlaceField, aby określić typy danych o miejscach, które mają być zwracane.
  5. Dodaj GMSAutocompleteFilter, aby ograniczyć zapytanie do określonego typu miejsca.
  6. Prezentuj GMSAutocompleteViewController za pomocą [self presentViewController...].
  7. Zarządzaj wyborem użytkownika w metodzie delegowania didAutocompleteWithPlace.
  8. Zamknij kontroler w metodach didAutocompleteWithPlace, didFailAutocompleteWithErrorwasCancelled.

Ten przykład ilustruje jeden z możliwych sposobów uruchomienia kontrolera GMSAutocompleteViewController 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

Jeśli chcesz mieć większą kontrolę nad interfejsem wprowadzania tekstu, użyj kontrolera wyników. Kontroler wyników dynamicznie włącza i wyłącza widoczność listy wyników w zależności od tego, który element interfejsu użytkownika jest aktywny.

Aby dodać do aplikacji kontroler wyników:

  1. Utwórz GMSAutocompleteResultsViewController.
    1. W nadrzędnym kontrolerze widoku zaimplementuj protokół GMSAutocompleteResultsViewControllerDelegate i przypisz go jako właściwość deleguowana.
  2. Utwórz obiekt UISearchController, przekazując jako argument kontrolera wyników obiekt GMSAutocompleteResultsViewController.
  3. Ustaw wartość GMSAutocompleteResultsViewController jako właściwość searchResultsUpdater elementu UISearchController.
  4. Dodaj searchBar UISearchController do interfejsu aplikacji.
  5. Zarządzaj wyborem użytkownika w metodzie delegowania didAutocompleteWithPlace.

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 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 do górnej części 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ślnie UISearchController ukrywa pasek nawigacyjny podczas prezentacji (można to wyłączyć). Jeśli pasek nawigacyjny jest widoczny i nieprzezroczysty, UISearchController nie ustawia prawidłowo położenia.

Aby obejść ten problem, użyj tego kodu:

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ą wyskakujących okienek z wynikami

Ten przykładowy kod pokazuje umieszczenie 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 aplikacja ma interfejs użytkownika do wyszukiwania niestandardowego tekstu, możesz użyć klasy GMSAutocompleteTableDataSource, aby wyświetlić widok tabeli z wynikami w kontrolerze widoku.

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

  1. W kontrolerze widoku zaimplementuj protokoły GMSAutocompleteTableDataSourceDelegateUISearchBarDelegate.
  2. Utwórz instancję GMSAutocompleteTableDataSource i przypisz kontroler widoku jako właściwość zastępczą.
  3. Ustaw parametr GMSAutocompleteTableDataSource jako źródło danych i właściwości delegowane instancji UITableView w kontrolerze widoku.
  4. W obiekcie obsługującym dane tekstowe wyszukiwania wywołaj funkcję sourceTextHasChanged obiektu GMSAutocompleteTableDataSource.
    1. Zarządzaj wyborem użytkownika w metodzie delegowania didAutocompleteWithPlace.
  5. Zamknij kontroler w metodach delegowanych didAutocompleteWithPlace, didFailAutocompleteWithError, wasCancelled.

Poniższy przykład kodu pokazuje, jak za pomocą klasy GMSAutocompleteTableDataSource wyświetlić widok tabeli elementu 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 ustawieniach interfejsu automatycznego uzupełniania, aby widżet lepiej pasował do wyglądu aplikacji. Kolory elementów sterujących w interfejsie można ustawić na 2 sposoby:

  • Za pomocą wbudowanego w iOS protokołu UIAppearance, aby w miarę możliwości nadawać styl elementom interfejsu użytkownika. Te ustawienia mają zastosowanie do wielu, ale nie wszystkich elementów sterujących interfejsu.
  • Używanie 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 używa kombinacji protokołu UIAppearance i metod pakietu SDK. Ten diagram pokazuje, które elementy można stylizować:

Kolory elementów sterujących autouzupełniania

W tabeli poniżej znajdziesz listę wszystkich elementów interfejsu użytkownika oraz informacje o tym, jak należy je stylizować (protokół UIAppearance lub metoda SDK).

Element interfejsu Metoda Poradniki i styl
Zabarwienie paska nawigacyjnego (tło) Protokół UIAppearance Zadzwoń pod numer setBarTintColor na serwerze proxy UINavigationBar.
Kolor zabarwienia paska nawigacyjnego (kursor na pasku wyszukiwania i przycisk Anuluj) Protokół UIAppearance Zadzwoń pod numer setTintColor na serwerze proxy UINavigationBar.
Kolor tekstu na pasku wyszukiwania Protokół UIAppearance Ustaw NSForegroundColorAttributeNamesearchBarTextAttributes.
Kolor odcienia paska wyszukiwania Nie dotyczy Pasek wyszukiwania jest przezroczysty i wyświetla się jako przyciemniona wersja paska nawigacyjnego.
Kolor tekstu zastępczego w pasku wyszukiwania (domyślny tekst wyszukiwania) Protokół UIAppearance Ustaw NSForegroundColorAttributeNameplaceholderAttributes.
Tekst główny (dotyczy też tekstu błędu i wiadomości) Metoda pakietu SDK Zadzwoń do firmy primaryTextColor.
Wyróżnienie tekstu głównego Metoda pakietu SDK Zadzwoń do firmy primaryTextHighlightColor.
Tekst dodatkowy Metoda pakietu SDK Zadzwoń do firmy secondaryTextColor.
Tekst błędu i komunikatu Metoda pakietu SDK Zadzwoń do firmy primaryTextColor.
Tło komórki tabeli Metoda pakietu SDK Zadzwoń do firmy tableCellBackgroundColor.
Kolor separatora komórek tabeli Metoda pakietu SDK Zadzwoń do firmy tableCellSeparatorColor.
Przycisk „Spróbuj ponownie” Metoda pakietu SDK Zadzwoń do firmy tintColor.
Wskaźnik aktywności (wskaźnik postępu) Protokół UIAppearance Zadzwoń pod numer setColor na serwerze proxy UIActivityIndicatorView.
Logo „Technologia Google”, smutna chmura Nie dotyczy Wersja biała lub szara jest wybierana automatycznie na podstawie kontrastu tła.
Ikona lupy i ikona wyczyszczania tekstu w polu tekstowym paska wyszukiwania Nie dotyczy Aby nadać styl, zastąp domyślne obrazy obrazami w wybranym kolorze.

Korzystanie z protokołu UIAppearance

Możesz użyć protokołu UIAppearance, aby uzyskać zastępstwo wyglądu dla danego elementu interfejsu. Następnie możesz użyć tego zastępstwa do ustawienia koloru elementu interfejsu. Gdy wprowadzisz zmianę, będzie ona dotyczyć wszystkich wystąpień danego elementu interfejsu. Na przykład w tym przykładzie kolor tekstu elementów klasy UITextField zmienia się globalnie na zielony, gdy są one zawarte w elementach klasy UISearchBar:

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

Więcej informacji o definiowaniu wartości kolorów znajdziesz w dokumentacji UIColor Class Reference (w języku angielskim).

Poniższe fragmenty kodu pokazują wszystkie polecenia zastępcze, których musisz użyć, aby stylizować wszystkie elementy w kontroli interfejsu użytkownika automatycznego uzupeł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 elementów sterujących interfejsu

Podzbiór elementów sterujących interfejsem użytkownika ma właściwości, na które nie ma wpływu protokół UIAppearance, dlatego muszą być one ustawiane bezpośrednio. Poniższy przykład kodu pokazuje definiowanie kolorów pierwszego planu i tła oraz ich stosowanie do instancji elementu sterującego interfejsu użytkownika 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;

Pobieranie prognoz dotyczących miejsc w sposób programowy

Możesz utworzyć niestandardowy interfejs wyszukiwania jako alternatywę dla interfejsu udostępnianego przez widżet autouzupełniania. W tym celu aplikacja musi pobierać prognozy dotyczące miejsc w ramach działania aplikacji. Aplikacja może uzyskać listę przewidywanych nazw lub adresów miejsc na jeden z tych sposobów:

Dzwonię do: GMSPlacesClient findAutocompletePredictionsFromQuery:

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

  • Ciąg autocompleteQuery zawierający tekst wpisany przez użytkownika.
  • GMSAutocompleteSessionToken, która służy do identyfikowania poszczególnych sesji. Aplikacja powinna przekazywać ten sam token w przypadku każdego wywołania żądania autouzupełniania, a potem ten token wraz z identyfikatorem miejsca w kolejnych wywołaniach fetchPlacefromPlaceID:, aby pobrać szczegóły miejsca wybranego przez użytkownika.
  • A GMSAutocompleteFilter to:
    • Możesz ograniczyć wyniki do konkretnego regionu.
    • Ogranicz wyniki do określonego typu miejsca.
    • Obiekt GMSPlaceLocationBias/Restriction, który powoduje, że wyniki są ograniczone do określonego obszaru określonego 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, Nowa Południowa Walia, Australia”. Każdy zakres tekstu pasujący do danych wprowadzonych przez użytkownika ma atrybut kGMSAutocompleteMatchAttribute. Możesz użyć tego atrybutu, aby wyróżnić pasujący tekst w zapytaniu użytkownika, jak pokazano poniżej.
  • placeID – identyfikator miejsca prognozowanego. Identyfikator miejsca to tekstowy identyfikator, który jednoznacznie identyfikuje miejsce. Więcej informacji o identyfikatorach miejsc znajdziesz w artykule Omówienie identyfikatorów miejsc.
  • distanceMeters – odległość w linii prostej od wskazanego punktu origin do miejsca docelowego. Jeśli właściwość origin nie zostanie skonfigurowana, wartość distance nie zostanie zwrócona.

Ten przykładowy kod pokazuje, jak za pomocą funkcji enumerateAttribute wyróżnić pogrubionym tekstem te 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 pobierania

Jeśli chcesz od podstaw utworzyć własne pole autouzupełniania, możesz użyć elementu sterującego GMSAutocompleteFetcher, który otacza metodę autocompleteQueryGMSPlacesClient. Pobierający ogranicza liczbę żądań, zwracając tylko wyniki dla ostatnio wpisanego tekstu wyszukiwania. Nie zawiera żadnych 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 pobieraniu, gdy użytkownik wpisze coś w polu tekstowym.
  4. Obsługuj prognozy i błędy za pomocą metod protokołów didAutcompleteWithPredictionsdidFailAutocompleteWithError.

Ten przykładowy kod pokazuje, jak za pomocą modułu pobierania pobrać dane wejściowe od użytkownika i wyświetlić dopasowania miejsc w widoku tekstowym. Funkcja wyboru miejsca została pominięta. Klasa FetcherSampleViewController pochodzi z klasy 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

Na potrzeby rozliczeń tokeny sesji łączą fazy zapytania i wyboru w autouzupełnianiu wyszukiwania w jedną sesję. Sesja rozpoczyna się, gdy użytkownik zacznie 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 wygenerować nowy token na każdą sesję. Zalecamy używanie tokenów sesji w przypadku wszystkich sesji automatycznego uzupełniania w ramach programowania (gdy używasz kontrolera pełnego ekranu lub kontrolera wyników, interfejs API automatycznie zadba o to).

Pakiet SDK Miejsc na iOS używa parametru GMSAutocompleteSessionToken do identyfikowania każdej sesji. Aplikacja powinna przekazać nowy token sesji na początku każdej nowej sesji, a potem ten sam token wraz z identyfikatorem miejsca w kolejnych wywołaniach 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 aplikacja korzysta z usługi autouzupełniania za pomocą kodu, interfejs musi wyświetlać informację „Technologia Google” lub być widoczny na mapie z logo Google.
  • Jeśli Twoja aplikacja korzysta z elementu sterującego autouzupełniania, nie musisz nic robić (wymagane informacje o pochodzeniu są wyświetlane domyślnie).
  • Jeśli po pobraniu miejsca po identyfikatorze wyświetlasz dodatkowe informacje o miejscu, musisz też wyświetlić atrybucję zewnętrznego źródła.

Więcej informacji znajdziesz w dokumentacji dotyczącej przypisywania zasług.

Sterowanie wskaźnikiem aktywności sieci

Aby sterować wskaźnikiem aktywności sieci na pasku stanu aplikacji, musisz zaimplementować odpowiednie opcjonalne metody delegowane dla klasy autocomplete, której używasz, oraz samodzielnie włączać i wyłączać wskaźnik sieci.

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

Dzięki wdrożeniu tych metod i ustawieniu wartości [UIApplication sharedApplication].networkActivityIndicatorVisible na YES oraz NO odpowiednio pasek stanu będzie prawidłowo pasował do interfejsu automatycznego uzupełniania.

Ograniczanie wyników autouzupełniania

Możesz ustawić element sterujący autouzupełniania, aby ograniczyć wyniki do określonego regionu geograficznego lub odfiltrować wyniki według jednego lub kilku typów miejsc albo według konkretnego kraju lub krajów. Aby ograniczyć wyniki, możesz:

  • Aby preferować (ustawić jako domyślne) wyniki z określonego regionu, ustaw locationBias na GMSAutocompleteFilter (nadal mogą być zwracane niektóre wyniki spoza zdefiniowanego regionu). Jeśli ustawiona jest też zasada locationRestriction, zasada locationBias zostanie zignorowana.
  • Aby wyświetlać (ograniczać) wyniki tylko w określonym regionie, ustaw parametr locationRestriction w elementach GMSAutocompleteFilter (zwracane będą tylko wyniki z określonego regionu).

    • Uwaga: to ograniczenie dotyczy tylko całych tras. Wyniki syntetyczne znajdujące się poza granicami prostokąta mogą być zwracane na podstawie trasy, która nakłada się na ograniczenie lokalizacji.
  • Aby zwrócić tylko wyniki zgodne z określonym typem miejsca, ustaw types na GMSAutocompleteFilter (np. podanie TypeFilter.ADDRESS spowoduje, że widget zwróci tylko wyniki z dokładnym adresem).

  • Aby zwrócić wyniki tylko z maksymalnie 5 wybranych krajów, ustaw parametr countries w elementach GMSAutocompleteFilter.

kierowanie wyników na określony region;

Aby preferować (bias) wyniki w określonym regionie, ustaw locationBias w, jak pokazano tutaj:GMSAutocompleteFilter

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 konkretnego regionu

Aby wyświetlać (ograniczać) wyniki tylko w określonym regionie, ustaw locationRestriction na GMSAutocompleteFilter, jak tutaj:

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 wybranych krajach, ustaw countries w polu GMSAutocompleteFilter, jak pokazano poniżej:

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ść typesGMSAutoCompleteFilter. Użyj tej właściwości, aby określić filtry wymienione w tabelach 1, 2 i 3 w przypadku PlaceTypes. Jeśli nie podasz żadnych typów, zwrócone zostaną wszystkie typy.

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

  • Użyj właściwości types, aby określić maksymalnie 5 wartości atrybutu 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ć zbiór typów z tabeli 3 na stronie Typy miejsc. Wartości kolekcji typu są definiowane przez stałe w GMSPlaceType.

    W żądaniu może być podany tylko 1 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 types w elementach GMSAutocompleteFilter. Ten przykład 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

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

Oto kilka ogólnych wskazówek:

  • Najszybszym sposobem na stworzenie działającego interfejsu użytkownika jest użycie: Widżetu autouzupełniania z Maps JavaScript API, Widżetu autouzupełniania z pakietu SDK Miejsc na Androida lub Widżetu autouzupełniania z pakietu SDK Miejsc na iOS.
  • Na początku zaznaj się z najważniejszymi polami danych usługi Autouzupełnianie miejsc.
  • Pola preferencji lokalizacji i ograniczeń lokalizacji są opcjonalne, ale mogą mieć znaczący wpływ na działanie funkcji autouzupełniania.
  • Użyj obsługi błędów, aby zapewnić płynne działanie aplikacji, jeśli interfejs API zwróci błąd.
  • Upewnij się, że aplikacja obsługuje przypadki, gdy nie ma wyboru, i oferuje użytkownikom sposób na kontynuowanie.

Sprawdzone metody optymalizacji kosztów

Podstawowa optymalizacja kosztów

Aby zoptymalizować koszty korzystania z usługi autouzupełniania miejsc, użyj masek pól w widżetach Szczegóły miejsca i Autouzupełnianie miejsc, aby zwracać tylko potrzebne pola z danymi o miejscach.

Zaawansowana optymalizacja kosztów

Rozważ automatyczne wdrażanie funkcji Autocomplete miejsc, aby uzyskać dostęp do cen za prośbę i wysłać wyniki interfejsu Geocoding API dotyczące wybranego miejsca zamiast Szczegółów miejsca. Cena taryfy „za żądanie” w połączeniu z interfejsem Geocoding API jest bardziej opłacalna niż taryfa „za sesję” (obejmująca poszczególne sesje) pod warunkiem spełnienia obu tych warunków:

  • Jeśli interesuje Cię tylko szerokość geograficzna, długość geograficzna lub adres wybranego miejsca przez użytkownika, interfejs Geocoding API dostarczy te informacje w mniejszym stopniu niż wywołanie interfejsu PlaceDetails.
  • Jeśli użytkownicy wybierają podpowiedzi autouzupełniania w ramach średnio 4 lub mniej żądań, cena za żądanie może być bardziej opłacalna niż cena za sesję.
Aby wybrać implementację Autouzupełniania miejsc dopasowaną do Twoich potrzeb, kliknij kartę odpowiadającą Twojej odpowiedzi na to pytanie.

Czy Twoja aplikacja wymaga jakichkolwiek informacji oprócz adresu i szerokości geograficznej/długości geograficznej wybranej prognozy?

Tak, potrzebuję więcej informacji

Używanie autouzupełniania miejsc na podstawie sesji z informacjami o miejscach.
Twoja aplikacja wymaga szczegółów miejsca, takich jak nazwa miejsca, stan firmy lub godziny otwarcia, dlatego implementacja autouzupełniania miejsc powinna używać tokenu sesji (programowo lub wbudowanego w widżety JavaScript, Android lub iOS), za co płacisz 0,017 USD za sesję plus odpowiedni SKU danych miejsc w zależności od tego, których pól danych miejsc używasz.1

Wdrażanie widżetów
Zarządzanie sesjami jest automatycznie wbudowane w widżety JavaScript, AndroidiOS. Obejmuje to zarówno żądania autouzupełniania dotyczące miejsc, jak i żądanie informacji o wybranym miejscu. Pamiętaj, aby określić parametr fields, aby mieć pewność, że żądasz tylko pol danych o miejscach, których potrzebujesz.

Wdrażanie automatyczne
Używaj tokenu sesji w żądaniach autouzupełniania miejsc. Gdy żądasz szczegółów miejsca dotyczących wybranej prognozy, uwzględnij te parametry:

  1. Identyfikator miejsca z odpowiedzi na autouzupełnianie miejsc
  2. token sesji użyty w żądaniu autouzupełniania miejsc.
  3. Parametr fields określający pola danych o miejscach, których potrzebujesz

Nie, potrzebny jest tylko adres i lokalizacja

W zależności od wydajności autouzupełniania miejsc interfejs Geocoding API może być dla Twojej aplikacji bardziej opłacalny niż interfejs Place Details. Skuteczność funkcji Autouzupełnianie w każdej aplikacji zależy od tego, co wpisują użytkownicy, gdzie jest używana aplikacja i czy zostały zastosowane sprawdzone metody optymalizacji skuteczności.

Aby odpowiedzieć na to pytanie, sprawdź, ile znaków użytkownik wpisze średnio przed wybraniem prognozy Miejsca w aplikacji.

Czy Twoi użytkownicy wybierają prognozę miejsca w autouzupełnianiu po średnio 4 lub mniej zapytaniach?

Tak

Zaimplementuj automatyczne uzupełnianie nazw miejsc za pomocą kodu, bez tokenów sesji, i wywołaj interfejs Geocoding API w przypadku wybranej prognozy miejsca.
Geocoding API dostarcza adresy i współrzędne szerokości i długości geograficznej za 0,005 USD za każde zapytanie. Przesyłanie 4 żądań Place Autocomplete – Per Request kosztuje 0,01132 USD, więc łączny koszt 4 żądań plus wywołania interfejsu Geocoding API dotyczącego wybranego miejsca to 0,01632 USD, co jest niższe niż cena autouzupełniania na sesję, która wynosi 0,017 USD na sesję.1

Rozważ zastosowanie sprawdzonych metod dotyczących wydajności, aby pomóc użytkownikom uzyskać prognozę, której szukają, w jeszcze krótszym ciągu znaków.

Nie

Używanie autouzupełniania miejsc na podstawie sesji z informacjami o miejscach.
Ponieważ średnia liczba żądań, które według Ciebie użytkownik wykona, zanim wybierze przewidywane wyniki autouzupełniania miejsc, przekracza koszt ustalany na podstawie sesji, implementacja autouzupełniania miejsc powinna używać tokenu sesji zarówno do żądań autouzupełniania miejsc, jak i powiązanych żądań szczegółów miejsca.Oznacza to łączny koszt 0,017 USD na sesję.1

Wdrażanie widżetów
Zarządzanie sesjami jest automatycznie wbudowane w widżety JavaScript, AndroidiOS. Obejmuje to zarówno żądania autouzupełniania dotyczące miejsc, jak i żądanie informacji o wybranym miejscu. Pamiętaj, aby określić parametr fields, aby mieć pewność, że żądasz tylko pól Dane podstawowe.

Wdrażanie automatyczne
Używaj tokenu sesji w żądaniach autouzupełniania miejsc. Gdy żądasz szczegółów miejsca dotyczących wybranej prognozy, uwzględnij te parametry:

  1. Identyfikator miejsca z odpowiedzi na autouzupełnianie miejsc
  2. token sesji użyty w żądaniu autouzupełniania miejsc.
  3. parametr fields określający pola Dane podstawowe, takie jak adres i geometria;

Rozważ opóźnianie wysyłania żądań do usługi Autocomplete miejsc
Możesz stosować strategie takie jak opóźnianie wysyłania żądań do usługi Autocomplete miejsc do momentu, gdy użytkownik wpisze pierwsze 3 lub 4 znaki, aby Twoja aplikacja wysyłała mniej żądań. Na przykład wysyłanie zapytań do Autocomplete w usłudze Places po wpisaniu przez użytkownika 3 znaku oznacza, że jeśli użytkownik wpisze 7 znaków, a potem wybierze podpowiedź, dla której wysyłasz 1 zapytanie do interfejsu Geocoding API, łączny koszt wyniesie 0,01632 USD (4 × 0,00283 USD za każde zapytanie do Autocomplete + 0,005 USD za geokodowanie).1

Jeśli opóźnienie żądań może spowodować, że średnia liczba żądań programowych będzie niższa niż 4, możesz postępować zgodnie z instrukcjami dotyczącymi skutecznego korzystania z interfejsu Place Autocomplete API z użyciem interfejsu Geocoding API. Pamiętaj, że opóźnianie żądań może być odbierane przez użytkownika jako opóźnienie przewidywania, ponieważ może on oczekiwać przewidywania przy każdym nowym naciśnięciu klawisza.

Rozważ zastosowanie sprawdzonych metod dotyczących wydajności, aby pomóc użytkownikom uzyskać prognozę, której szukają, w mniejszej liczbie znaków.


  1. Koszty podane w tym miejscu są podane w USD. Pełne informacje o cenach znajdziesz na stronie Płatności za korzystanie z Google Maps Platform.

Sprawdzone metody dotyczące wydajności

W tych wytycznych znajdziesz wskazówki dotyczące optymalizacji działania autouzupełniania w Google Maps:

  • Dodaj ograniczenia dotyczące kraju, preferencje dotyczące lokalizacji oraz (w przypadku implementacji programowych) preferencje językowe do implementacji funkcji Autouzupełniania miejsc. W przypadku widżetów nie trzeba podawać preferencji językowych, ponieważ są one pobierane z przeglądarki lub urządzenia mobilnego użytkownika.
  • Jeśli autouzupełnianie miejsc jest wyświetlane z mapą, możesz dostosować lokalizację do widoku mapy.
  • Jeśli użytkownik nie wybierze żadnej z podpowiedzi autouzupełniania, ponieważ żadna z nich nie jest pożądanym adresem, możesz ponownie użyć oryginalnego danych wejściowych użytkownika, aby uzyskać bardziej trafne wyniki:
    • Jeśli oczekujesz, że użytkownik poda tylko informacje o adresie, ponownie użyj 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 znajdowania miejsca. Jeśli wyniki mają być uzyskiwane tylko w konkretnym regionie, użyj ustawienia lokalizacji.
    Inne scenariusze, w których warto użyć interfejsu Geocoding API:
    • Użytkownicy wpisują adresy pomieszczeń w budynku, np. adresy konkretnych lokali lub apartamentów. Na przykład czeski adres „Stroupežnického 3191/17, Praha” daje częściową podpowiedź w autouzupełnianiu adresów.
    • 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

Chociaż może wystąpić wiele różnych błędów, większość z nich jest zwykle spowodowana błędami konfiguracji (np. użyto nieprawidłowego klucza API lub klucz API został źle skonfigurowany) lub błędami dotyczącymi limitu (aplikacja przekroczyła swój limit). Więcej informacji o limitach znajdziesz w artykule Limity wykorzystania.

Błędy występujące podczas korzystania z ustawień autouzupełniania są zwracane w metodie didFailAutocompleteWithError() różnych protokołów delegowanych. Właściwość code dostarczonego obiektu NSError ma ustawioną jedną z wartości wyliczenia GMSPlacesErrorCode.