地点自动补全

请选择平台: Android iOS JavaScript 网络服务

<ph type="x-smartling-placeholder">

Places SDK for iOS 中的自动补全服务会返回地点 来响应用户搜索查询。在用户输入内容时, 自动填充服务会返回有关地点(如商家、 地址、Plus 代码和 地图注点。

您可以通过以下方式向应用中添加自动填充服务:

添加自动补全界面控件

自动补全界面控件是具有内置自动补全功能的搜索对话框 功能在用户输入搜索字词时,该控件会显示 可供选择的预测地点列表。当用户做出选择时 GMSPlace 该实例后,您的应用可以使用它来获取有关 所选地点。

您可以使用以下方式将自动填充 UI 控件添加到应用中:

添加全屏控件

当您需要模态上下文时,使用全屏控件,其中 自动补全界面会暂时替换应用的界面,直到 用户做出了选择。此功能由 GMSAutocompleteViewController 类。当用户选择一个地点后,您的应用会收到回调。

要向应用中添加全屏控件,请执行以下操作:

  1. 在主应用中创建界面元素,以启动自动补全界面控件, 例如 UIButton 上的触摸处理程序。
  2. 实现 GMSAutocompleteViewControllerDelegate 协议。
  3. 创建 GMSAutocompleteViewController 的实例 并将父视图控制器分配为委托属性。
  4. 创建 GMSPlaceField 以定义要返回的地点数据类型。
  5. 添加GMSAutocompleteFilter 将查询限定为特定地点类型
  6. 展示GMSAutocompleteViewController 使用 [self presentViewController...]
  7. didAutocompleteWithPlace 中处理用户的选择 委托方法。
  8. didAutocompleteWithPlace 中关闭该控制器, didFailAutocompleteWithErrorwasCancelled 委托方法。

以下示例演示了一种可能的启动方式, GMSAutocompleteViewController 以响应用户点按按钮的操作。

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

添加结果控制器

如果您想更好地控制文本输入界面,请使用结果控制器。 结果控制器可动态切换结果列表的可见性 根据输入界面焦点进行调整。

要向应用中添加结果控制器,请执行以下操作:

  1. 创建 GMSAutocompleteResultsViewController
  2. 实现 GMSAutocompleteResultsViewControllerDelegate 协议,并将父视图控制器指定为 委托属性。
  3. 创建一个 UISearchController 对象,并传入 GMSAutocompleteResultsViewController 作为结果控制器参数。
  4. 设置 GMSAutocompleteResultsViewController UISearchControllersearchResultsUpdater 属性。
  5. UISearchControllersearchBar 添加到应用界面中。
  6. didAutocompleteWithPlace 中处理用户的选择 委托方法。

您可以通过多种方式将 UISearchController 的搜索栏放置在 应用界面:

向导航栏添加搜索栏

以下代码示例展示了如何添加结果控制器、 searchBar 添加到导航栏,并处理用户的选择:

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

在视图顶部添加搜索栏

以下代码示例展示了如何将 searchBar 添加到视图顶部。

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

默认情况下,UISearchController 在演示时隐藏导航栏(可以停用)。如果 导航栏可见且不透明,UISearchController 未设置 正确放置该展示位置。

请使用以下代码解决这一问题:

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;

添加使用弹出式窗口结果的搜索栏

以下代码示例展示了如何将搜索栏放置在 导航栏,以及在弹出式窗口中显示搜索结果。

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

使用表数据源

如果您的应用具有自定义搜索文本界面,您可以使用 GMSAutocompleteTableDataSource 类来驱动在视图控制器上显示结果的表格视图。

使用GMSAutocompleteTableDataSource 作为 UITableView 的数据源和代理 在视图控制器中:

  1. 实现 GMSAutocompleteTableDataSourceDelegateUISearchBarDelegate 协议。
  2. 创建 GMSAutocompleteTableDataSource 实例,并将视图控制器分配为委托属性。
  3. 设置 GMSAutocompleteTableDataSource 作为 UITableView 的数据源和委托属性 实例
  4. 在搜索文本输入的处理程序中,对sourceTextHasChanged GMSAutocompleteTableDataSource
  5. didAutocompleteWithPlace 委托方法中处理用户的选择。
  6. didAutocompleteWithPlacedidFailAutocompleteWithErrorwasCancelled 委托方法。

以下代码示例演示了如何使用 GMSAutocompleteTableDataSource 类在单独添加 UISearchBar 时驱动 UIViewController 的表视图。

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

      

自定义文本和背景颜色

您可以在自动补全界面中设置所有文本和背景的颜色 使 widget 与应用的视觉外观更匹配 设置 UI 控件颜色的方式有以下两种:

  • 尽可能使用原生 iOS UIAppearance 协议全局设置界面控件的样式。这些设置适用于很多(但不是全部)界面控件 元素。
  • 使用微件类中的 SDK 方法来设置 UIAppearance 协议不支持。

通常,您的应用会使用 UIAppearance 协议的某种组合 和 SDK 方法。下图显示可以设置样式的元素:

自动补全界面控件颜色

下表列出了所有界面元素,并说明了每个元素 一个应设置样式(UIAppearance 协议或 SDK 方法)。

界面元素 方法 造型百科
导航栏色调(背景) UIAppearance 协议 UINavigationBar 代理上调用 setBarTintColor
导航栏着色颜色(搜索栏文本插入符号和“取消”按钮) UIAppearance 协议 UINavigationBar 代理上调用 setTintColor
搜索栏文字颜色 UIAppearance 协议 searchBarTextAttributes 中设置 NSForegroundColorAttributeName
搜索栏着色颜色 不适用 搜索栏是半透明的,并显示为阴影版本 导航栏
搜索栏占位符文本颜色(默认搜索文本) UIAppearance 协议 placeholderAttributes 中设置 NSForegroundColorAttributeName
主要文本(也会应用于错误和消息文本) SDK 方法 欢迎致电primaryTextColor
主要文本突出显示 SDK 方法 欢迎致电primaryTextHighlightColor
辅助文本 SDK 方法 欢迎致电secondaryTextColor
错误和消息文本 SDK 方法 欢迎致电primaryTextColor
表格单元格背景 SDK 方法 欢迎致电tableCellBackgroundColor
表格单元格分隔符颜色 SDK 方法 欢迎致电tableCellSeparatorColor
“重试”按钮 SDK 方法 欢迎致电tintColor
活动指示器(进度旋转图标) UIAppearance 协议 UIActivityIndicatorView 代理上调用 setColor
“由 Google 提供支持”徽标,悲伤的云朵图片 不适用 系统会根据背景对比度自动选择白色或灰色版本。
搜索栏文本字段中的放大镜和清除文本图标 不适用 要设置样式,请将默认图片替换为所需颜色的图片。

使用 UIAppearance 协议

您可以使用 UIAppearance 协议 来获取指定界面元素的外观代理,然后您可以使用该代理 用于设置界面元素的颜色。修改后,所有 都会受到影响例如,以下全局变量 将 UITextField 类的文本颜色更改为绿色 包含在 UISearchBar 中:

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

有关定义颜色值的详情,请参考 UIColor 类参考

以下代码段显示了运行命令时需要使用的所有代理命令 设置全屏自动补全界面控件中所有字段的样式。添加此代码 添加到 Appdelegate.m 中的 didFinishLaunchingWithOptions 方法:

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

设置界面控件样式属性

界面控件元素的子集具有不受 UIAppearance 协议,因此必须直接设置。以下代码示例 展示了如何定义前景色和背景色,以及如何将这些颜色应用于界面 名为 acController 的控制实例。将此代码添加到 onLaunchClicked 方法:

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;

以编程方式获取地点预测结果

您可以创建自定义搜索用户界面,作为 自动补全 widget。为此,您的应用必须获取地点预测 以编程方式您的应用可以获得预测地点名称和/或 通过以下其中一种方式指定地址:

正在呼叫GMSPlacesClient findAutocompletePredictionsFromQuery:

若要获取预测地点名称和/或地址的列表,请先 实例化 GMSPlacesClient, 然后调用 GMSPlacesClient findAutocompletePredictionsFromQuery: 方法:

  • autocompleteQuery 字符串,包含用户输入的文本。
  • GMSAutocompleteSessionToken、 用于标识每个会话您的应用应 然后为每次“自动补全”请求调用传递相同的令牌,然后传递该令牌, 和地点 ID,在对 fetchPlacefromPlaceID: 的后续调用中 可检索用户所选地点的地点详情。
  • GMSAutocompleteFilter 用于:
    • 自定义调整结果,或将结果限制在特定区域。
    • 将结果限定为特定地点类型
    • 一个 GMSPlaceLocationBias/Restriction 对象,用于使结果自定义调整为由纬度和经度边界指定的特定区域。
  • 用于处理返回的预测结果的回调方法。

以下代码示例展示了对 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);
    }
  }
}];

API 调用指定的回调方法,传入 GMSAutocompletePrediction 对象的操作。

每个GMSAutocompletePrediction 对象包含以下信息:

  • attributedFullText - 预测结果的完整文本,格式为 一个 NSAttributedString。例如,“Sydney Opera House, Sydney, New South “澳大利亚威尔士”。每个与用户输入匹配的文本范围都有一个 属性 kGMSAutocompleteMatchAttribute。您可以使用此属性 例如,突出显示用户查询中的匹配文本,如下所示。
  • placeID - 预测地点的地点 ID。地点 ID 是 用于唯一标识地点的文本标识符。如需详细了解 地点 ID,请参阅地点 ID 概览
  • distanceMeters - 与指定的 origin到目的地。如果未设置 origin 属性,则没有距离 返回的值。

以下代码示例说明了如何以粗体文本突出显示 使用 enumerateAttribute,指定与用户查询中的文本匹配的结果的个数:

Swift

let regularFont = UIFont.systemFont(ofSize: UIFont.labelFontSize)
let boldFont = UIFont.boldSystemFont(ofSize: UIFont.labelFontSize)

let bolded = prediction.attributedFullText.mutableCopy() as! NSMutableAttributedString
bolded.enumerateAttribute(kGMSAutocompleteMatchAttribute, in: NSMakeRange(0, bolded.length), options: []) {
  (value, range: NSRange, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
    let font = (value == nil) ? regularFont : boldFont
    bolded.addAttribute(NSFontAttributeName, value: font, range: range)
}

label.attributedText = bolded
    

Objective-C

UIFont *regularFont = [UIFont systemFontOfSize:[UIFont labelFontSize]];
UIFont *boldFont = [UIFont boldSystemFontOfSize:[UIFont labelFontSize]];

NSMutableAttributedString *bolded = [prediction.attributedFullText mutableCopy];
[bolded enumerateAttribute:kGMSAutocompleteMatchAttribute
                   inRange:NSMakeRange(0, bolded.length)
                   options:0
                usingBlock:^(id value, NSRange range, BOOL *stop) {
                  UIFont *font = (value == nil) ? regularFont : boldFont;
                  [bolded addAttribute:NSFontAttributeName value:font range:range];
                }];

label.attributedText = bolded;
    

使用提取程序

如果您想从头开始构建自己的自动补全控件,可以使用 GMSAutocompleteFetcher、 它会在 GMSPlacesClient 上封装 autocompleteQuery 方法。 提取程序限制请求,仅返回最近日期的结果 输入的搜索文本。它不提供 UI 元素。

如需实现 GMSAutocompleteFetcher,请执行以下操作: 请按以下步骤操作:

  1. 实现 GMSAutocompleteFetcherDelegate 协议。
  2. 创建一个 GMSAutocompleteFetcher 对象。
  3. 在用户输入内容时,对提取程序调用 sourceTextHasChanged
  4. 使用 didAutcompleteWithPredictions 处理预测和错误 和didFailAutocompleteWithError 协议方法。

以下代码示例演示了如何使用提取程序获取用户输入 以及在文本视图中显示地点匹配项。用于选择地点的功能 已省略。FetcherSampleViewController 派生自 UIViewController 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

会话令牌

会话令牌对用户自动补全的查询和选择阶段进行分组 出于结算目的搜索单独的会话。会话开始于 用户开始输入查询,并在选择地点时结束。每个 会话中可以有多个查询,并随后选择一个地点。在 会话结束,令牌已失效;您的应用必须生成 每次会话的新令牌。我们建议对每个 Pod 都使用会话令牌 程序化自动填充会话(当您使用全屏控制器时, 或结果控制器,API 会自动执行该操作)。

Places SDK for iOS 使用 GMSAutocompleteSessionToken 识别每个会话之后,您的应用应传递一个新的会话令牌。 然后传递同一令牌和地点 ID, 在对 fetchPlacefromPlaceID: 的后续调用中 可检索用户所选地点的地点详情。

详细了解会话令牌

使用以下代码生成新的会话令牌:

let token: GMSAutocompleteSessionToken = GMSAutocompleteSessionToken.init()

用量限额

在应用中显示提供方说明

  • 如果您的应用以编程方式使用自动填充服务,您的界面必须 显示“由 Google 强力驱动”或者出现在 Google 品牌地图。
  • 如果您的应用使用自动补全界面控件,则无需执行其他操作 (默认显示必需的提供方说明)。
  • 如果您在之后检索并显示其他地点信息, 根据 ID 获取地点, 您还必须显示第三方出处。

有关详情,请参阅 归因

控制网络活动指示器

要控制应用状态栏中的网络活动指示器,您需要 必须为自动补全功能实现适当的可选委托方法 类,然后自行打开和关闭网络指示器。

  • 对于 GMSAutocompleteViewController,您必须实现委托方法 didRequestAutocompletePredictions:didUpdateAutocompletePredictions:
  • 对于 GMSAutocompleteResultsViewController,您必须实现委托方法 didRequestAutocompletePredictionsForResultsController:didUpdateAutocompletePredictionsForResultsController:
  • 对于 GMSAutocompleteTableDataSource,您必须实现委托方法 didRequestAutocompletePredictionsForTableDataSource:didUpdateAutocompletePredictionsForTableDataSource:

通过实现这些方法并设置 [UIApplication sharedApplication].networkActivityIndicatorVisible 分别设置为 YESNO,则状态栏会正确匹配 自动填充界面。

限制自动补全结果

您可以设置自动补全界面控件,以便将结果限制在某个特定 地理区域,和/或对结果进行过滤,以便仅显示一个或多个地点类型,或者 特定国家/地区。如需限制结果,您可以执行以下操作:

  • 优先显示指定区域内的结果(偏差),请将 locationBias 设置为开启 GMSAutocompleteFilter(某些来自指定区域以外的结果可能会 )。如果还设置了 locationRestriction,则系统将忽略 locationBias
  • 如需仅显示(限制)指定区域内的结果,请将 GMSAutocompleteFilter上的locationRestriction(仅限 指定的区域)。

    • 注意:此限制仅适用于整个路线(合成 可根据路线返回位于矩形边界之外的结果 与地理位置限制重叠
  • 要仅返回符合特定地点类型的结果,请设置 typesGMSAutocompleteFilter 上(例如,指定 TypeFilter.ADDRESS) 将导致 widget 仅返回具有精确地址的结果)。

  • 要仅返回最多五个指定国家/地区内的结果,请将 GMSAutocompleteFiltercountries

使结果偏向于特定区域

优先显示指定区域内的结果(偏差),请将 locationBias 设置为开启 GMSAutocompleteFilter,如下所示:

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

将结果限定为特定区域

如需仅显示(限制)指定区域内的结果,请将 locationRestriction(在 GMSAutocompleteFilter 上),如下所示:

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

按国家/地区过滤结果

要过滤最多 5 个指定国家/地区内的结果,请将 countries 设置为开启 GMSAutocompleteFilter,如下所示:

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

按地点类型或类型集合过滤结果

通过设置 types 属性 GMSAutoCompleteFilter。 使用此属性可指定 地点类型。若未指定任何类型,系统将返回所有类型。

要指定类型或类型集合过滤条件,请执行以下操作:

  • 使用 types 属性指定表 1 中的五个 type 值 如地点类型部分所示。类型值包括 由 GMSPlaceType 中的常量定义。

  • 使用 types 属性指定表 3 中的类型集合 请参阅地点类型一文。类型集合值由 GMSPlaceType 中的常量。

    只能在请求中使用表 3 中的一种类型。如果您指定 值,但不能指定表 1 或表 2 中的值。如果 就会出错

例如,要仅返回符合特定地点类型的结果,请将 GMSAutocompleteFiltertypes。以下示例展示了如何设置 过滤器以仅返回具有精确地址的结果:

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

地点自动补全优化

本部分介绍了帮助您充分利用地点自动补全服务的最佳实践。

下面列出了一些一般准则:

  • 若要开发可正常运行的界面,最快的方式是使用 Maps JavaScript API Autocomplete widget、Places SDK for Android Autocomplete widget 或 Places SDK for iOS Autocomplete 界面控件
  • 从一开始就了解重要的地点自动补全数据字段
  • 位置自定义调整和位置限制字段是可选的,但可能会对自动补全性能产生重大影响。
  • 使用错误处理可确保您的应用在 API 返回错误时妥善降级。
  • 请确保您的应用可以处理没有选择任何内容的情况,并能够让用户继续操作。

费用优化最佳实践

基本费用优化

为了优化地点自动补全服务的使用费用,请在地点详情和地点自动补全 widget 中使用字段掩码,以便仅返回所需的地点数据字段

高级费用优化

请考虑通过程序化方式实现地点自动补全,以便采用“按请求”定价模式,并请求关于所选地点(而不是地点详情)的 Geocoding API 结果。如果同时满足以下两个条件,与采用“按会话”(基于会话)定价模式相比,将“按请求”定价模式与 Geocoding API 搭配使用的性价比更高:

  • 如果您只需要用户所选地点的纬度/经度或地址,那么采用 Geocoding API 提供此类信息所需的费用会低于调用地点详情。
  • 如果用户平均在不超过四次自动补全预测请求之内选择自动补全预测结果,那么“按请求”定价模式可能会比“按会话”定价模式的性价比更高。
如果在选择符合您需求的地点自动补全实现方面需要帮助,请选择与以下问题的答案相对应的标签页。

除了所选预测结果的地址和纬度/经度外,您的应用是否需要任何其他信息?

是,需要更多详细信息

将基于会话的地点自动补全与地点详情搭配使用
由于您的应用需要地点名称、商家状态或营业时间等地点详情,因此您的地点自动补全实现应使用会话令牌(以程序化方式构建,或内置到 JavaScriptAndroidiOS widget 中),总费用为每次会话 0.017 美元,外加相应的地点数据 SKU 费用(具体取决于您申请的地点数据字段)。1

widget 实现
会话管理功能自动内置于 JavaScriptAndroidiOS widget 中。这包括针对所选预测结果的“地点自动补全”请求和“地点详情”请求。请务必指定 fields 参数,以确保您只请求所需的地点数据字段

程序化实现
在“地点自动补全”请求中使用会话令牌。在请求关于所选预测结果的地点详情时,添加以下参数:

  1. “地点自动补全”响应中的地点 ID
  2. “地点自动补全”请求中使用的会话令牌
  3. fields 参数,用于指定您所需的地点数据字段

否,只需要地址和位置信息

对于您的应用,Geocoding API 可能比地点详情性价比更高,具体取决于您使用地点自动补全的性能。每个应用的自动补全效率各有不同,具体取决于用户输入的内容、使用应用所在的位置,以及是否遵循了性能优化最佳实践

为了回答以下问题,请分析用户在您的应用中选择地点自动补全预测结果之前平均会输入多少个字符。

平均而言,用户是否能够在不超过四次请求之内选择地点自动补全预测结果?

在不使用会话令牌的情况下以程序化方式实现地点自动补全,并针对所选的地点预测调用 Geocoding API。
Geocoding API 提供地址和纬度/经度坐标,价格为每个请求 0.005 美元。发出四次地点自动补全 - 按请求结算请求的费用为 0.01132 美元,因此四次请求加上针对所选地点预测调用 Geocoding API 的总费用将为 0.01632 美元,低于按会话结算的自动补全价格(即每次会话 0.017 美元)。1

您可以考虑采用性能最佳实践,帮助用户以更少的字符找到所需的预测结果。

将基于会话的地点自动补全与地点详情搭配使用
由于您预计在用户选择地点自动补全预测结果之前应用发出的平均请求次数较多,所需费用会超过“按会话”定价模式的费用,因此建议您在实现地点自动补全时,针对“地点自动补全”请求和关联的“地点详情”请求使用会话令牌,总费用为每次会话 0.017 美元。1

widget 实现
会话管理功能自动内置于 JavaScriptAndroidiOS widget 中。这包括针对所选预测结果的“地点自动补全”请求和“地点详情”请求。请务必指定 fields 参数,以确保您只请求基本数据字段。

程序化实现
在“地点自动补全”请求中使用会话令牌。在请求关于所选预测结果的地点详情时,添加以下参数:

  1. “地点自动补全”响应中的地点 ID
  2. “地点自动补全”请求中使用的会话令牌
  3. fields 参数,用于指定地址和几何图形等基本数据字段

考虑延迟“地点自动补全”请求
您可以采取一些策略,例如延迟“地点自动补全”请求,直到用户输入前三个或四个字符,从而减少应用发出的请求数量。例如,在用户输入第三个字符后针对每个字符发出“地点自动补全”请求,也就是说,如果用户输入七个字符,然后选择了您发出一次 Geocoding API 请求所获得的预测结果,总费用将为:0.01632 美元(4 * 0.00283 美元 [自动补全 - 按请求结算] + 0.005 美元 [地理编码])。1

如果延迟请求会导致平均程序化请求次数低于四次,您可以按照使用 Geocoding API 提高地点自动补全性能的实现指南操作。请注意,如果用户希望每次输入新的字符后都能看到预测结果,可能会将延迟请求视为时间上的延迟。

您可以考虑采用性能最佳实践,帮助用户以较少的字符找到所需的预测结果。


  1. 此处所列的费用以美元为单位。如需了解完整的定价信息,请参阅 Google Maps Platform 结算页面。

性能最佳实践

下面的指南介绍了优化地点自动补全性能的方式:

  • 向地点自动补全实现添加国家/地区限制、位置自定义调整和语言偏好设置(适用于程序化实现)。您无需为 widget 进行语言偏好设置,因为它们会从用户的浏览器或移动设备中选择语言偏好设置。
  • 如果地点自动补全附有地图,您可以根据地图视口来设置位置偏向。
  • 如果用户未选择任一自动补全预测结果,通常是因为这些预测结果都不是所需的结果地址,您可以重复使用原始用户输入来尝试获取更相关的结果: 适合回退到 Geocoding API 的其他场景包括:
    • 用户在针对 subpremise 地址的地点自动补全支持不完整的国家/地区(例如捷克、爱沙尼亚和立陶宛)输入 subpremise 地址。例如,捷克地址“Stroupežnického 3191/17, Praha”会在地点自动补全中生成部分预测结果。
    • 用户在输入地址时,需要输入路段前缀,例如纽约的“23-30 29th St, Queens”或夏威夷考爱岛“47-380 Kamehameha Hwy, Kaneohe”。

问题排查

虽然错误很常见,但大部分错误都是 通常是由配置错误(例如 例如,使用的 API 密钥有误,或已配置 API 密钥 错误)或配额错误(您的应用已超出其配额)。请参阅 用量限额 详细了解配额

使用自动完成控件时发生的错误会在 didFailAutocompleteWithError() 方法。通过 提供的 NSError 对象的 code 属性设置为 GMSPlacesErrorCode 枚举。