Autouzupełnianie miejsc

Usługa autouzupełniania w pakiecie SDK Miejsc na iOS zwraca prognozy dotyczące miejsc w odpowiedzi na zapytania użytkowników. W miarę wpisywania tekstu przez użytkownika usługa autouzupełniania 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 do interfejsu

Element sterujący autouzupełniania w interfejsie to okno wyszukiwania z wbudowanymi funkcjami autouzupełniania. Gdy użytkownik wpisuje wyszukiwane słowa, element sterujący wyświetla listę przewidywanych miejsc do wyboru. Gdy użytkownik dokona wyboru, zwracana jest instancja GMSPlace, której aplikacja może potem użyć, aby uzyskać szczegółowe informacje o wybranym miejscu.

Element interfejsu autouzupełniania możesz dodać do aplikacji w jeden z tych sposobów:

Dodawanie elementu sterującego na pełnym ekranie

Użyj elementu sterującego pełnego ekranu, jeśli potrzebujesz kontekstu modalnego, w którym interfejs autouzupełniania tymczasowo zastępuje interfejs aplikacji, dopóki użytkownik nie dokona wyboru. Ta funkcja jest udostępniana przez klasę GMSAutocompleteViewController. Gdy użytkownik wybierze miejsce, do aplikacji zostanie oddzwonione.

Aby dodać do aplikacji element sterujący na pełnym ekranie:

  1. Utwórz element interfejsu w głównej aplikacji, aby uruchomić element sterujący autouzupełniania w interfejsie, np. moduł obsługi dotykowej na urządzeniu UIButton.
  2. Zaimplementuj protokół GMSAutocompleteViewControllerDelegate w kontrolerze widoku nadrzędnego.
  3. Utwórz instancję GMSAutocompleteViewController i przypisz nadrzędny kontroler widoku danych jako właściwość przedstawiciela.
  4. Utwórz obiekt GMSPlaceField, aby określić typy danych miejsc, które mają być zwracane.
  5. Aby ograniczyć zapytanie do określonego typu miejsca, dodaj GMSAutocompleteFilter.
  6. Zaprezentuj GMSAutocompleteViewController za pomocą [self presentViewController...].
  7. Obsługa wyboru użytkownika w metodzie przekazywania uprawnień didAutocompleteWithPlace.
  8. Zamknij kontroler w metodach przekazywania didAutocompleteWithPlace, didFailAutocompleteWithError i wasCancelled.

Ten przykład przedstawia jeden z możliwych sposobów uruchomienia 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:NSSelectorFromString(@"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 przełącza widoczność listy wyników na podstawie zaznaczenia interfejsu wprowadzania.

Aby dodać kontroler wyników do aplikacji:

  1. Utwórz GMSAutocompleteResultsViewController.
  2. Zaimplementuj protokół GMSAutocompleteResultsViewControllerDelegate w kontrolerze widoku nadrzędnego i przypisz kontroler widoku nadrzędnego jako właściwość delegacji.
  3. Utwórz obiekt UISearchController, przekazując do GMSAutocompleteResultsViewController jako argument kontrolera wyników.
  4. Ustaw GMSAutocompleteResultsViewController jako właściwość searchResultsUpdater elementu UISearchController.
  5. Dodaj pole searchBar dla aplikacji UISearchController do interfejsu użytkownika aplikacji.
  6. Obsługa wyboru użytkownika w metodzie przekazywania uprawnień didAutocompleteWithPlace.

Pasek wyszukiwania obiektu 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 do paska nawigacyjnego 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ładowy kod pokazuje dodawanie elementu searchBar na górze 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 będzie prawidłowo wskazywać miejsca docelowego.

Aby obejść ten problem, użyj następującego 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ącego okienka wyników

Poniższy przykładowy kod pokazuje, jak umieścić pasek wyszukiwania po prawej stronie paska nawigacyjnego i wyświetlić wyniki 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;
}

Za pomocą źródła danych tabeli

Jeśli Twoja aplikacja ma interfejs tekstowy wyszukiwania niestandardowego, możesz użyć klasy GMSAutocompleteTableDataSource, aby uruchomić widok tabeli, w którym będą wyświetlane wyniki w kontrolerze widoku.

Aby użyć narzędzia GMSAutocompleteTableDataSource jako źródła danych i przekazać dostęp do komponentu UITableView w kontrolerze widoków:

  1. Zaimplementuj protokoły GMSAutocompleteTableDataSourceDelegate i UISearchBarDelegate w kontrolerze widoku.
  2. utworzyć instancję GMSAutocompleteTableDataSource i przypisać kontroler widoku jako właściwość przedstawiciela;
  3. Ustaw GMSAutocompleteTableDataSource jako źródło danych i przekaż właściwości instancji UITableView w kontrolerze widoku danych.
  4. W module obsługi wpisywania tekstu wyszukiwania wywołaj sourceTextHasChanged w GMSAutocompleteTableDataSource.
  5. Przetwórz wybór użytkownika w metodzie przekazywania dostępu w didAutocompleteWithPlace.
  6. Zamknij kontroler w metodach przekazywania didAutocompleteWithPlace, didFailAutocompleteWithError, wasCancelled.

Ten przykładowy kod pokazuje, jak używać klasy GMSAutocompleteTableDataSource do sterowania widokiem tabeli w UIViewController, gdy UISearchBar został dodany oddzielnie.

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

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

  • Przez używanie natywnego protokołu UIAppearance na iOS w celu globalnego stylu elementów interfejsu, gdy jest to możliwe. Te ustawienia dotyczą wielu, ale nie wszystkich elementów interfejsu.
  • Przez wykorzystanie metod pakietu SDK w klasach widżetów w celu ustawienia 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. Na poniższym diagramie pokazano, których elementów można stylizować:

Kolory elementów sterujących autouzupełniania interfejsu

Tabela poniżej zawiera listę wszystkich elementów interfejsu i wskazuje, jakie powinny mieć styl (protokół UIAppearance lub metoda SDK).

Element interfejsu Metoda Poradniki i styl
Odcień paska nawigacyjnego (tło) Protokół UIAppearance Wywołaj setBarTintColor przez serwer proxy UINavigationBar.
Kolor odcienia paska nawigacyjnego (karetka tekstu na pasku wyszukiwania i przycisk Anuluj) Protokół UIAppearance Wywołaj setTintColor przez serwer proxy UINavigationBar.
Kolor tekstu na pasku wyszukiwania Protokół UIAppearance Ustaw NSForegroundColorAttributeName w komórce searchBarTextAttributes.
Kolor odcienia paska wyszukiwania Nie dotyczy Pasek wyszukiwania jest półprzezroczysty i wyświetlany jako zacieniona wersja paska nawigacyjnego.
Kolor tekstu zastępczego paska wyszukiwania (domyślny tekst wyszukiwania) Protokół UIAppearance Ustaw NSForegroundColorAttributeName w komórce placeholderAttributes.
Tekst podstawowy (dotyczy również tekstu błędu i komunikatu) Metoda przy użyciu pakietu SDK Zadzwoń do firmy primaryTextColor.
Wyróżnienie tekstu głównego Metoda przy użyciu pakietu SDK Zadzwoń do firmy primaryTextHighlightColor.
Tekst dodatkowy Metoda przy użyciu pakietu SDK Zadzwoń do firmy secondaryTextColor.
Błąd i tekst wiadomości Metoda przy użyciu pakietu SDK Zadzwoń do firmy primaryTextColor.
Tło komórki tabeli Metoda przy użyciu pakietu SDK Zadzwoń do firmy tableCellBackgroundColor.
Kolor separatora komórek tabeli Metoda przy użyciu pakietu SDK Zadzwoń do firmy tableCellSeparatorColor.
Przycisk „Spróbuj ponownie” Metoda przy użyciu pakietu SDK Zadzwoń do firmy tintColor.
Wskaźnik aktywności (wskaźnik postępu) Protokół UIAppearance Wywołaj setColor przez serwer proxy UIActivityIndicatorView.
Logo „Powered by Google”, Smutna chmura Nie dotyczy Wersja biała lub szara jest wybierana automatycznie na podstawie kontrastu tła.
Ikony lupy i czystego tekstu w polu tekstowym na pasku wyszukiwania Nie dotyczy Aby zmienić 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 dla danego elementu interfejsu, a następnie użyć go do ustawienia koloru tego elementu. Modyfikacja wpływa na wszystkie wystąpienia danego elementu UI. W tym przykładzie w poniższym przykładzie kolor tekstu klas UITextField zmienia się na zielony, jeśli są one zawarte w klasie UISearchBar:

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

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

Poniższe fragmenty kodu pokazują wszystkie polecenia serwera proxy, których musisz użyć, aby określić styl w interfejsie autouzupełniania na pełnym ekranie. Dodaj ten kod do metody didFinishLaunchingWithOptions w 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

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

Automatyczne uzyskiwanie prognoz dotyczących miejsc

Jako alternatywę dla interfejsu udostępnianego przez widżet autouzupełniania możesz utworzyć niestandardowy interfejs wyszukiwania. Aplikacja musi wtedy automatycznie otrzymywać prognozy dotyczące miejsc. Aplikacja może uzyskać listę przewidywanych nazw miejsc lub adresów na jeden z tych sposobów:

Dzwonię pod GMSPlacesClient findAutocompletePredictionsFromQuery:

Aby uzyskać listę przewidywanych nazw miejsc lub adresów, zainicjuj GMSPlacesClient, a potem wywołaj metodę GMSPlacesClient findAutocompletePredictionsFromQuery: z następującymi parametrami:

  • Ciąg tekstowy autocompleteQuery zawierający tekst wpisany przez użytkownika.
  • GMSAutocompleteSessionToken, który służy do identyfikowania poszczególnych sesji. Aplikacja powinna przekazywać ten sam token dla każdego wywołania żądania autouzupełniania, a następnie przekazywać ten token wraz z identyfikatorem miejsca w kolejnym wywołaniu funkcji fetchPlacefromPlaceID:, aby pobrać informacje o miejscu wybranym przez użytkownika.
  • GMSAutocompleteFilter:
    • Uprzedź lub ogranicz wyniki do konkretnego regionu.
    • Ogranicz wyniki do określonego typu miejsca.
    • Obiekt GMSPlaceLocationBias/ograniczenia promujący wyniki 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.

W przykładach poniżej pokazujemy 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 postaci NSAttributedString. Przykład: „Sydney Opera House, Sydney, Nowa Południowa Walia, Australia”. Każdy zakres tekstu, który pasuje 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 przewidywanego miejsca. 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ść bezpośrednia od wskazanego miejsca (origin) do miejsca docelowego. Jeśli właściwość origin nie jest skonfigurowana, nie jest zwracana żadna wartość odległości.

Ten przykładowy kod ilustruje, jak za pomocą pogrubionego tekstu wyróżnić za pomocą enumerateAttribute 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 modułu pobierania

Jeśli chcesz utworzyć własny element sterujący autouzupełniania od zera, możesz użyć polecenia GMSAutocompleteFetcher, które opakowuje metodę autocompleteQuery w GMSPlacesClient. Moduł pobierania ogranicza liczbę żądań i zwraca tylko wyniki dla ostatnio wpisanego tekstu. Nie zawiera elementów interfejsu.

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

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

Poniższy przykładowy kod pokazuje, jak za pomocą modułu pobierania pobierać dane wejściowe użytkownika i wyświetlać dopasowania do miejsc w widoku tekstowym. Pominięto funkcję wyboru miejsca. FetcherSampleViewController uzyskuje dane z UIViewController w 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>
#import <GoogleMapsBase/GoogleMapsBase.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 oddzielną sesję na potrzeby rozliczeń. Sesja rozpoczyna się, gdy użytkownik zaczyna wpisywać zapytanie, a kończy się, gdy wybierze miejsce. Każda sesja może zawierać wiele zapytań, a następnie wybór jednego miejsca. Po zakończeniu sesji token straci ważność – aplikacja musi generować nowy token dla każdej sesji. Zalecamy używanie tokenów sesji we wszystkich sesjach automatycznego autouzupełniania (jeśli używasz kontrolera pełnoekranowego lub kontrolera wyników, interfejs API zajmie się tym automatycznie).

Pakiet Places SDK na iOS używa do identyfikowania sesji identyfikatora GMSAutocompleteSessionToken. Aplikacja powinna przekazywać nowy token sesji przy rozpoczęciu każdej nowej sesji, a następnie przekazywać ten sam token wraz z identyfikatorem miejsca w kolejnym wywołaniu funkcji fetchPlacefromPlaceID:, aby pobrać informacje o miejscu wybranym 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 automatycznie, jej interfejs musi wyświetlać informację „Technologia Google” lub znajdować się na mapie marki Google.
  • Jeśli Twoja aplikacja używa elementu sterującego autouzupełniania w interfejsie użytkownika, nie musisz niczego robić (domyślnie wyświetlana jest wymagana atrybucja).
  • Jeśli pobierasz i wyświetlasz dodatkowe informacje o miejscu po uzyskaniu miejsca na podstawie identyfikatora, musisz też uwzględnić informacje o ich źródłach.

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 przekazywania dostępu dla używanej klasy autouzupełniania oraz samodzielnie włączyć i wyłączyć wskaźnik sieci.

  • W przypadku GMSAutocompleteViewController musisz wdrożyć metody przekazywania didRequestAutocompletePredictions: i didUpdateAutocompletePredictions:.
  • W przypadku GMSAutocompleteResultsViewController musisz wdrożyć metody przekazywania didRequestAutocompletePredictionsForResultsController: i didUpdateAutocompletePredictionsForResultsController:.
  • W przypadku GMSAutocompleteTableDataSource musisz wdrożyć metody przekazywania didRequestAutocompletePredictionsForTableDataSource: i didUpdateAutocompletePredictionsForTableDataSource:.

Jeśli zaimplementujesz te metody i ustawisz [UIApplication sharedApplication].networkActivityIndicatorVisible na YES oraz NO, pasek stanu będzie prawidłowo dopasowany do interfejsu autouzupełniania.

Ogranicz wyniki autouzupełniania

W interfejsie autouzupełniania możesz ustawić ograniczenie wyników do konkretnego regionu geograficznego lub filtrowanie wyników według jednego lub kilku typów miejsc bądź konkretnego kraju bądź kraju. Aby ograniczyć wyniki, możesz wykonać te czynności:

  • Aby preferować (odchylenia) wyniki w zdefiniowanym regionie, ustaw locationBias w GMSAutocompleteFilter (niektóre wyniki spoza zdefiniowanego regionu mogą nadal być zwracane). Jeśli ustawiono także locationRestriction, parametr locationBias będzie ignorowany.
  • Aby wyświetlać tylko (ograniczenia) wyniki w zdefiniowanym regionie, ustaw locationRestriction w GMSAutocompleteFilter (zwracane będą tylko wyniki ze wskazanego regionu).

    • Uwaga: to ograniczenie dotyczy tylko całych tras. Wyniki syntetyczne znajdujące się poza prostokątnymi granicami mogą być zwracane w przypadku trasy, która pokrywa się z ograniczeniem lokalizacji.
  • Aby zwracać tylko wyniki zgodne z określonym typem miejsca, ustaw types w elemencie GMSAutocompleteFilter. Na przykład określenie filtra 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, w GMSAutocompleteFilter ustaw countries.

Uprzedzenia wyników w konkretnym regionie

Aby preferować (odchylenia) wyniki w zdefiniowanym regionie, ustaw locationBias w GMSAutocompleteFilter w następujący sposób:

  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 w usłudze GMSAutocompleteFilter w ten sposób:

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

Filtruj wyniki według kraju

Aby filtrować wyniki z maksymalnie 5 określonych krajów, w kolumnie GMSAutocompleteFilter ustaw countries, jak w tym przykładzie:

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

Filtruj wyniki według typu miejsca lub typu kolekcji

Ogranicz zbieranie wyników do określonego typu lub typu, ustawiając właściwość types właściwości GMSAutoCompleteFilter. Za pomocą tej właściwości możesz określić filtry wymienione w tabelach 1, 2 i 3 w typach miejsc. Jeśli nic nie zostanie określone, zwracane są wszystkie typy.

Aby określić filtr kolekcji typu lub typu:

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

  • Użyj właściwości types, aby określić zbiór typu z tabeli 3 przedstawiony w sekcji Typy miejsc. Wartości zbioru typów są definiowane przez stałe w narzędziu GMSPlaceType.

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

Aby na przykład zwracać tylko wyniki pasujące do określonego typu miejsca, ustaw types w elemencie GMSAutocompleteFilter. Oto przykład, jak ustawić filtr tak, aby zwracał tylko wyniki z dokładnym adresem:

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

Optymalizacja miejsca autouzupełniania

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

Oto kilka ogólnych wskazówek:

  • Najszybszym sposobem na stworzenie działającego interfejsu użytkownika jest użycie widżetu autouzupełniania interfejsu Maps JavaScript API, widżetu autouzupełniania z pakietu SDK Miejsc na Androida lub widżetu autouzupełniania z pakietu SDK Miejsc na iOS elementu interfejsu użytkownika autouzupełniania
  • Od razu poznaj najważniejsze pola danych autouzupełniania miejsc.
  • Pola promowania lokalizacji i ograniczenia lokalizacji są opcjonalne, ale mogą mieć znaczny wpływ na działanie autouzupełniania.
  • Korzystaj z obsługi błędów, aby mieć pewność, że aplikacja bez problemów przestanie działać, gdy interfejs API zwróci błąd.
  • Sprawdź, czy aplikacja działa, gdy nie ma wyboru, i daje użytkownikom możliwość kontynuowania.

Sprawdzone metody optymalizacji kosztów

Podstawowa optymalizacja kosztów

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

Zaawansowana optymalizacja kosztów

Rozważ zautomatyzowaną implementację autouzupełniania miejsc, aby uzyskać dostęp do cen na żądanie i wysyłać żądania wyników interfejsu Geocoding API dotyczących wybranego miejsca zamiast szczegółów miejsca. Model cenowy za żądanie w połączeniu z interfejsem Geocoding API jest bardziej opłacalny niż model cenowy za sesję (na podstawie sesji), jeśli spełnione są oba te warunki:

  • Jeśli potrzebujesz tylko szerokości i długości geograficznej lub adresu wybranego przez użytkownika miejsca, interfejs Geocoding API dostarcza te informacje dla mniej niż wywołania Place Details.
  • Jeśli użytkownicy wybiorą podpowiedź autouzupełniania w zakresie nie więcej niż 4 żądań podpowiedzi autouzupełniania, model cenowy za żądanie może być bardziej opłacalny niż model płatności za sesję.
Aby uzyskać pomoc w wyborze odpowiedniego wdrożenia autouzupełniania miejsc, wybierz kartę, która odpowiada Twojej odpowiedzi na to pytanie.

Czy aplikacja wymaga innych informacji poza adresem i szerokością geograficzną wybranej prognozy?

Tak, potrzebujemy więcej informacji

Korzystaj z autouzupełniania miejsc opartego na sesji, korzystając z szczegółów miejsca.
Twoja aplikacja wymaga informacji o miejscach, takich jak nazwa miejsca, status firmy lub godziny otwarcia, dlatego implementacja autouzupełniania miejsc powinna korzystać z tokenu sesji (programowego lub wbudowanego w widżety JavaScript, Androida bądź iOS.Koszt to 0,017 USD za sesję plus odpowiednie kody SKU danych miejsc w zależności od tego, o jakie pola danych miejsc prosisz.

Implementacja widżetów
Zarządzanie sesjami jest automatycznie wbudowane w widżety JavaScript oraz Android lub iOS. Obejmuje to zarówno żądania autouzupełniania miejsc, jak i żądania szczegółów miejsca dotyczące wybranej prognozy. Pamiętaj, by określić parametr fields, aby mieć pewność, że wysyłasz tylko żądanie pól danych o miejscu, których potrzebujesz.

Implementacja automatyzacji
W żądaniach autouzupełniania miejsc używaj tokena sesji. W żądaniu Szczegóły miejsca dotyczące wybranej prognozy podaj te parametry:

  1. identyfikator miejsca z odpowiedzi na autouzupełnianie miejsca,
  2. Token sesji używany w żądaniu autouzupełniania miejsca.
  3. Parametr fields określający potrzebne pola danych o miejscu

Nie, wymaga tylko adresu i lokalizacji

Interfejs Geocoding API może być tańszą opcją niż informacje o miejscu, w zależności od tego, jak dobrze korzystasz z autouzupełniania. Skuteczność autouzupełniania każdej aplikacji różni się w zależności od tego, co wpisują użytkownicy, gdzie aplikacja jest używana i czy wdrożone zostały sprawdzone metody dotyczące optymalizacji wydajności.

Aby odpowiedzieć na poniższe pytanie, przed wybraniem podpowiedzi autouzupełniania miejsca w aplikacji sprawdź, ile znaków średnio wpisuje użytkownik.

Czy użytkownicy wybierają podpowiedzi autouzupełniania miejsca średnio w przypadku 4 żądań lub mniejszej liczby żądań?

Tak

Zaimplementuj autouzupełnianie miejsc automatycznie bez tokenów sesji i wywołuj interfejs Geocoding API dla prognozy wybranego miejsca.
Geocoding API dostarcza adresy oraz współrzędne szerokości i długości geograficznej za 0,005 USD za żądanie. Utworzenie 4 żądań typu Place Autocomplete – Per Request (Autouzupełnianie – według żądania) kosztuje 0,01132 USD, więc łączny koszt 4 żądań plus wywołania Geocoding API dla wybranej prognozy miejsca wynosi 0,01632 USD, czyli mniej niż cena autouzupełniania na sesję, która wynosi 0,017 USD za sesję1.

Zastanów się nad skorzystaniem ze sprawdzonych metod dotyczących skuteczności, aby pomóc użytkownikom uzyskać podpowiedzi, których szukają, przy użyciu jeszcze mniejszej liczby znaków.

Nie

Korzystaj z autouzupełniania miejsc opartego na sesji, korzystając z szczegółów miejsca.
Średnia liczba spodziewanych żądań, które zostaną wysłane, zanim użytkownik wybierze prognozę autouzupełniania miejsca, przekracza koszt ceny za sesję. Dlatego Twoja implementacja autouzupełniania miejsc powinna korzystać z tokenu sesji zarówno dla żądań autouzupełniania miejsc, jak i powiązanych z nimi żądań informacji o miejscach. Ich łączny koszt to 0,017 USD za sesję1.

Implementacja widżetów
Zarządzanie sesjami jest automatycznie wbudowane w widżety JavaScript oraz Android lub iOS. Obejmuje to zarówno żądania autouzupełniania miejsc, jak i żądania szczegółów miejsca dotyczące wybranej prognozy. Pamiętaj, by określić parametr fields, aby mieć pewność, że żądanie dotyczy tylko pól danych podstawowych.

Implementacja automatyzacji
W żądaniach autouzupełniania miejsc używaj tokena sesji. W żądaniu Szczegóły miejsca dotyczące wybranej prognozy podaj te parametry:

  1. identyfikator miejsca z odpowiedzi na autouzupełnianie miejsca,
  2. Token sesji używany w żądaniu autouzupełniania miejsca.
  3. Parametr fields określający pola Dane podstawowe, takie jak adres i geometria

Rozważ opóźnienie żądań autouzupełniania miejsc
Aby zmniejszyć liczbę żądań, możesz zastosować takie strategie jak opóźnienie żądania autouzupełniania miejsca do wpisania przez użytkownika pierwszych 3 lub 4 znaków. Na przykład wykonywanie żądań autouzupełniania miejsc dla każdego znaku po wpisaniu trzeciego znaku przez użytkownika oznacza, że jeśli użytkownik wpisze 7 znaków, a potem wybierze prognozę, dla której utworzysz jedno żądanie do interfejsu Geocoding API, łączny koszt wyniesie 0,01632 USD (4 * 0,00283 Autouzupełniaj na żądanie + 0,005 USD za kodowanie geograficzne)1.

Jeśli opóźnienie żądań może spowodować, że średnia liczba żądań automatyzacji spadnie poniżej 4, postępuj zgodnie ze wskazówkami dotyczącymi skutecznej implementacji autouzupełniania miejsc za pomocą interfejsu Geocoding API. Pamiętaj, że opóźnienie żądań może być postrzegane jako opóźnienie przez użytkownika, który może oczekiwać podpowiedzi po każdym naciśnięciu klawisza.

Zastanów się nad skorzystaniem ze sprawdzonych metod dotyczących skuteczności, aby pomóc użytkownikom uzyskać spodziewaną prognozę przy użyciu mniejszej liczby znaków.


  1. Podane tu koszty są podane w dolarach amerykańskich. Pełne ceny znajdziesz na stronie płatności za Google Maps Platform.

Sprawdzone metody zwiększania skuteczności

Poniższe wskazówki opisują sposoby optymalizacji skuteczności autouzupełniania miejsc:

  • Dodaj do implementacji autouzupełniania miejsc ograniczenia związane z krajem, promowaniem lokalizacji i (w przypadku automatyzacji) ustawienia języka. W przypadku widżetów preferencje językowe nie są wymagane, ponieważ wybierają one język z przeglądarki użytkownika lub urządzenia mobilnego.
  • Jeśli wraz z mapą jest wyświetlana mapa, możesz dostosować lokalizację według widocznego obszaru mapy.
  • Jeśli użytkownik nie wybierze żadnej z podpowiedzi autouzupełniania, zwykle dlatego, że żadna z tych podpowiedzi nie odpowiada docelowemu adresowi wyniku, możesz ponownie wykorzystać dane wejściowe użytkownika, by uzyskać bardziej trafne wyniki:
    • Jeśli oczekujesz, że użytkownik wpisze tylko informacje adresowe, w wywołaniu interfejsu Geocoding API użyj tych samych danych wejściowych.
    • Jeśli spodziewasz się, że użytkownik będzie wpisywać zapytania dotyczące konkretnego miejsca, podając nazwę lub adres, użyj funkcji Znajdź zgłoszenie miejsca. Jeśli wyniki są oczekiwane tylko w konkretnym regionie, użyj promowania lokalizacji.
    Inne scenariusze, w których najlepiej skorzystać z interfejsu Geocoding API, to:
    • Użytkownicy podający adresy podrzędne w krajach, w których obsługa autouzupełniania miejsc w przypadku adresów podrzędnych jest niekompletna, np. w Czechach, Estonii i Litwie. Na przykład adres w języku czeskim „Stroupežnického 3191/17, Praha” generuje częściową prognozę w autouzupełnianiu miejsca.
    • Użytkownicy, którzy wpisują adresy z prefiksami fragmentu drogi, takimi jak „23-30 29th St, Queens” w Nowym Jorku lub „47-380 Kamehameha Hwy, Kaneohe” na wyspie Kauai na Hawajach.

Rozwiązywanie problemów

Błędy mogą być różne, ale większość z nich wynika z błędów konfiguracji (np. użycia niewłaściwego klucza interfejsu API lub jego nieprawidłowej konfiguracji) bądź błędów limitu (aplikacja przekroczyła limit miejsca). Więcej informacji o limitach znajdziesz w sekcji Limity wykorzystania.

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