Dịch vụ tự động hoàn thành trong Places SDK cho iOS trả về các đề xuất về địa điểm để phản hồi các cụm từ tìm kiếm của người dùng. Khi người dùng nhập, dịch vụ tự động hoàn thành sẽ trả về các đề xuất cho những địa điểm như doanh nghiệp, địa chỉ, mã cộng và địa điểm yêu thích.
Bạn có thể thêm tính năng tự động hoàn thành vào ứng dụng theo những cách sau:
- Thêm một chế độ kiểm soát giao diện người dùng tự động hoàn thành để tiết kiệm thời gian phát triển và đảm bảo trải nghiệm nhất quán cho người dùng.
- Nhận thông tin dự đoán về địa điểm theo phương thức lập trình để tạo trải nghiệm người dùng tuỳ chỉnh.
Thêm một chế độ kiểm soát giao diện người dùng tự động hoàn thành
Thành phần giao diện người dùng tự động hoàn thành là một hộp thoại tìm kiếm có chức năng tự động hoàn thành tích hợp. Khi người dùng nhập cụm từ tìm kiếm, chế độ kiểm soát sẽ hiển thị một danh sách các địa điểm dự đoán để người dùng chọn. Khi người dùng chọn một mục, một thực thể GMSPlace
sẽ được trả về. Sau đó, ứng dụng của bạn có thể dùng thực thể này để lấy thông tin chi tiết về địa điểm đã chọn.
Bạn có thể thêm chế độ kiểm soát giao diện người dùng tự động hoàn thành vào ứng dụng theo những cách sau:
Thêm chế độ điều khiển toàn màn hình
Sử dụng chế độ kiểm soát toàn màn hình khi bạn muốn có một bối cảnh phương thức, trong đó giao diện người dùng tự động hoàn thành sẽ tạm thời thay thế giao diện người dùng của ứng dụng cho đến khi người dùng chọn xong. Chức năng này do lớp GMSAutocompleteViewController
cung cấp. Khi người dùng chọn một địa điểm, ứng dụng của bạn sẽ nhận được một lệnh gọi lại.
Cách thêm chế độ điều khiển toàn màn hình vào ứng dụng:
- Tạo một phần tử trên giao diện người dùng trong ứng dụng chính để chạy chế độ kiểm soát giao diện người dùng tự động hoàn tất, ví dụ: trình xử lý thao tác chạm trên
UIButton
. - Triển khai giao thức
GMSAutocompleteViewControllerDelegate
trong trình điều khiển chế độ xem mẹ. - Tạo một thực thể của
GMSAutocompleteViewController
và chỉ định trình điều khiển chế độ xem gốc làm thuộc tính uỷ quyền. - Tạo một
GMSPlaceField
để xác định các loại dữ liệu địa điểm cần trả về. - Thêm
GMSAutocompleteFilter
để giới hạn cụm từ tìm kiếm ở một loại địa điểm cụ thể. - Hiển thị
GMSAutocompleteViewController
bằng[self presentViewController...]
. - Xử lý lựa chọn của người dùng trong phương thức uỷ quyền
didAutocompleteWithPlace
. - Đóng bộ điều khiển trong các phương thức uỷ quyền
didAutocompleteWithPlace
,didFailAutocompleteWithError
vàwasCancelled
.
Ví dụ sau đây minh hoạ một cách có thể để chạy GMSAutocompleteViewController
để phản hồi khi người dùng nhấn vào một nút.
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
Thêm bộ điều khiển kết quả
Sử dụng bộ điều khiển kết quả khi bạn muốn kiểm soát nhiều hơn đối với giao diện người dùng nhập văn bản. Trình điều khiển kết quả sẽ bật/tắt chế độ hiển thị của danh sách kết quả một cách linh hoạt dựa trên tiêu điểm giao diện người dùng đầu vào.
Cách thêm một bộ điều khiển kết quả vào ứng dụng của bạn:
- Tạo một
GMSAutocompleteResultsViewController
.- Triển khai giao thức
GMSAutocompleteResultsViewControllerDelegate
trong trình điều khiển khung hiển thị mẹ và chỉ định trình điều khiển khung hiển thị mẹ làm thuộc tính uỷ quyền.
- Triển khai giao thức
- Tạo một đối tượng
UISearchController
, truyềnGMSAutocompleteResultsViewController
làm đối số của bộ điều khiển kết quả. - Đặt
GMSAutocompleteResultsViewController
làm thuộc tínhsearchResultsUpdater
củaUISearchController
. - Thêm
searchBar
choUISearchController
vào giao diện người dùng của ứng dụng. - Xử lý lựa chọn của người dùng trong phương thức uỷ quyền
didAutocompleteWithPlace
.
Có một số cách để đặt thanh tìm kiếm của UISearchController
vào giao diện người dùng của ứng dụng:
- Thêm thanh tìm kiếm vào thanh điều hướng
- Thêm một thanh tìm kiếm vào đầu khung hiển thị
- Thêm thanh tìm kiếm bằng kết quả bật lên
Thêm thanh tìm kiếm vào thanh điều hướng
Ví dụ về mã sau đây minh hoạ cách thêm một bộ điều khiển kết quả, thêm searchBar
vào thanh điều hướng và xử lý lựa chọn của người dùng:
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; }
Thêm một thanh tìm kiếm vào đầu khung hiển thị
Ví dụ về đoạn mã sau đây cho thấy cách thêm searchBar
vào đầu một khung hiển thị.
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; }
Theo mặc định, UISearchController
sẽ ẩn thanh điều hướng khi trình bày (bạn có thể tắt chế độ này). Trong trường hợp thanh điều hướng hiển thị và không trong suốt, UISearchController
sẽ không đặt vị trí chính xác.
Hãy sử dụng mã sau đây để khắc phục vấn đề:
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;
Thêm thanh tìm kiếm bằng kết quả bật lên
Ví dụ về mã sau đây cho thấy cách đặt một thanh tìm kiếm ở bên phải của thanh điều hướng và hiển thị kết quả trong một cửa sổ bật lên.
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; }
Sử dụng nguồn dữ liệu bảng
Nếu ứng dụng của bạn có giao diện người dùng văn bản tìm kiếm tuỳ chỉnh, bạn có thể sử dụng lớp GMSAutocompleteTableDataSource
để điều khiển bảng hiển thị kết quả trên bộ điều khiển chế độ xem.
Cách sử dụng GMSAutocompleteTableDataSource
làm nguồn dữ liệu và uỷ quyền cho UITableView
trong một trình xem:
- Triển khai giao thức
GMSAutocompleteTableDataSourceDelegate
vàUISearchBarDelegate
trong trình điều khiển khung hiển thị. - Tạo một thực thể
GMSAutocompleteTableDataSource
và chỉ định bộ điều khiển khung hiển thị làm thuộc tính uỷ quyền. - Đặt
GMSAutocompleteTableDataSource
làm nguồn dữ liệu và uỷ quyền các thuộc tính của thực thểUITableView
trên trình điều khiển chế độ xem. - Trong trình xử lý cho dữ liệu đầu vào văn bản tìm kiếm, hãy gọi
sourceTextHasChanged
trênGMSAutocompleteTableDataSource
.- Xử lý lựa chọn của người dùng trong phương thức uỷ quyền
didAutocompleteWithPlace
.
- Xử lý lựa chọn của người dùng trong phương thức uỷ quyền
- Đóng bộ điều khiển trong các phương thức uỷ quyền
didAutocompleteWithPlace
,didFailAutocompleteWithError
,wasCancelled
.
Ví dụ về mã sau đây minh hoạ cách dùng lớp GMSAutocompleteTableDataSource
để điều khiển chế độ xem bảng của UIViewController
khi UISearchBar
được thêm riêng.
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
Tuỳ chỉnh màu văn bản và màu nền
Bạn có thể đặt màu cho tất cả văn bản và nền trong chế độ kiểm soát giao diện người dùng tự động hoàn thành để tiện ích này phù hợp hơn với giao diện trực quan của ứng dụng. Có hai cách để đặt màu cho chế độ điều khiển trên giao diện người dùng:
- Bằng cách sử dụng giao thức UIAppearance tích hợp sẵn trên iOS để tạo kiểu cho các thành phần điều khiển trên giao diện người dùng trên toàn cầu (nếu có thể). Các chế độ cài đặt này áp dụng cho nhiều (nhưng không phải tất cả) thành phần điều khiển trên giao diện người dùng.
- Bằng cách sử dụng các phương thức SDK trên các lớp tiện ích để đặt những thuộc tính không được giao thức UIAppearance hỗ trợ.
Thông thường, ứng dụng của bạn sẽ sử dụng một số tổ hợp của giao thức UIAppearance và các phương thức SDK. Sơ đồ sau đây cho biết những phần tử có thể được tạo kiểu:
Bảng sau đây liệt kê tất cả các phần tử trên giao diện người dùng và cho biết cách tạo kiểu cho từng phần tử (giao thức UIAppearance hoặc phương thức SDK).
Phần tử trên giao diện người dùng | Phương thức | Hướng dẫn định phong cách |
---|---|---|
Màu sắc của thanh điều hướng (nền) | Giao thức UIAppearance | Gọi setBarTintColor trên proxy UINavigationBar . |
Màu sắc của thanh điều hướng (dấu nháy văn bản trên thanh tìm kiếm và nút Huỷ) | Giao thức UIAppearance | Gọi setTintColor trên proxy UINavigationBar . |
Màu văn bản của thanh tìm kiếm | Giao thức UIAppearance | Đặt NSForegroundColorAttributeName trong searchBarTextAttributes . |
Màu phủ của thanh tìm kiếm | Không áp dụng | Thanh tìm kiếm có màu trong mờ và sẽ hiển thị dưới dạng phiên bản có bóng của Thanh điều hướng. |
Màu văn bản của trình giữ chỗ trên thanh tìm kiếm (văn bản tìm kiếm mặc định) | Giao thức UIAppearance | Đặt NSForegroundColorAttributeName trong placeholderAttributes . |
Văn bản chính (cũng áp dụng cho văn bản lỗi và văn bản thông báo) | Phương thức SDK | Gọi cho primaryTextColor . |
Văn bản chính được đánh dấu | Phương thức SDK | Gọi cho primaryTextHighlightColor . |
Văn bản phụ | Phương thức SDK | Gọi cho secondaryTextColor . |
Lỗi và nội dung thông báo | Phương thức SDK | Gọi cho primaryTextColor . |
Nền ô trong bảng | Phương thức SDK | Gọi cho tableCellBackgroundColor . |
Màu của dấu phân cách ô trong bảng | Phương thức SDK | Gọi cho tableCellSeparatorColor . |
Nút "Thử lại" | Phương thức SDK | Gọi cho tintColor . |
Chỉ báo hoạt động (vòng quay tiến trình) | Giao thức UIAppearance | Gọi setColor trên proxy UIActivityIndicatorView . |
Biểu trưng "Powered by Google", hình ảnh Đám mây buồn | Không áp dụng | Phiên bản màu trắng hoặc xám sẽ được chọn tự động dựa trên độ tương phản của nền. |
Biểu tượng kính lúp và biểu tượng xoá văn bản trong trường văn bản của Thanh tìm kiếm | Không áp dụng | Để tạo kiểu, hãy thay thế hình ảnh mặc định bằng hình ảnh có màu sắc mong muốn. |
Sử dụng giao thức UIAppearance
Bạn có thể sử dụng giao thức UIAppearance để lấy proxy giao diện cho một thành phần trên giao diện người dùng nhất định. Sau đó, bạn có thể dùng proxy này để đặt màu cho thành phần đó. Khi bạn sửa đổi, tất cả các phiên bản của một phần tử giao diện người dùng nhất định đều sẽ bị ảnh hưởng. Ví dụ: ví dụ sau đây sẽ thay đổi màu văn bản của các lớp UITextField
thành màu xanh lục trên toàn cục khi các lớp này nằm trong một UISearchBar
:
[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setDefaultTextAttributes:@{NSForegroundColorAttributeName:[UIColor greenColor]}];
Để biết thêm thông tin về cách xác định giá trị màu, hãy tham khảo Tài liệu tham khảo về lớp UIColor.
Các đoạn mã sau đây cho thấy tất cả các lệnh proxy mà bạn cần dùng để tạo kiểu cho mọi thứ trong chế độ điều khiển giao diện người dùng tự động hoàn thành ở chế độ toàn màn hình. Thêm mã này vào phương thức didFinishLaunchingWithOptions
trong 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;
Đặt các thuộc tính kiểu điều khiển giao diện người dùng
Một số phần tử điều khiển giao diện người dùng có các thuộc tính không bị ảnh hưởng bởi giao thức UIAppearance, do đó, bạn phải đặt trực tiếp. Ví dụ về mã sau đây cho thấy cách xác định màu nền trước và màu nền, đồng thời áp dụng các màu này cho một thực thể điều khiển giao diện người dùng có tên là acController
. Thêm mã này vào phương thức onLaunchClicked
trong 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;
Nhận thông tin dự đoán về địa điểm theo phương thức lập trình
Bạn có thể tạo giao diện người dùng tìm kiếm tuỳ chỉnh thay cho giao diện người dùng do tiện ích tự động hoàn thành cung cấp. Để làm được việc này, ứng dụng của bạn phải nhận được các dự đoán về địa điểm theo phương thức lập trình. Ứng dụng của bạn có thể nhận được danh sách tên và/hoặc địa chỉ được dự đoán của địa điểm theo một trong những cách sau:
Đang gọi cho GMSPlacesClient findAutocompletePredictionsFromQuery:
Để nhận danh sách tên và/hoặc địa chỉ được dự đoán của địa điểm, trước tiên, hãy khởi tạo GMSPlacesClient, sau đó gọi phương thức GMSPlacesClient
findAutocompletePredictionsFromQuery:
bằng các tham số sau:
- Một chuỗi
autocompleteQuery
chứa văn bản do người dùng nhập. GMSAutocompleteSessionToken
, được dùng để xác định từng phiên riêng lẻ. Ứng dụng của bạn phải truyền cùng một mã thông báo cho mỗi lệnh gọi yêu cầu tự động hoàn thành, sau đó truyền mã thông báo đó cùng với một Mã địa điểm trong lệnh gọi tiếp theo đếnfetchPlacefromPlaceID:
để truy xuất Thông tin chi tiết về địa điểm cho địa điểm mà người dùng đã chọn.- A
GMSAutocompleteFilter
đến:- Thiên vị hoặc hạn chế kết quả ở một khu vực cụ thể.
- Giới hạn kết quả ở một loại địa điểm cụ thể.
- Một đối tượng
GMSPlaceLocationBias
/Restriction làm sai lệch kết quả đến một khu vực cụ thể do các giới hạn về vĩ độ và kinh độ chỉ định.
- Một phương thức gọi lại để xử lý các dự đoán được trả về.
Các ví dụ về mã bên dưới cho thấy một lệnh gọi đến 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 này gọi phương thức gọi lại được chỉ định, truyền vào một mảng các đối tượng GMSAutocompletePrediction
.
Mỗi đối tượng GMSAutocompletePrediction
chứa thông tin sau:
attributedFullText
– Toàn văn nội dung đề xuất, dưới dạngNSAttributedString
. Ví dụ: "Nhà hát Opera Sydney, Sydney, New South Wales, Úc". Mọi dải văn bản khớp với nội dung người dùng nhập đều có một thuộc tính,kGMSAutocompleteMatchAttribute
. Bạn có thể sử dụng thuộc tính này để làm nổi bật văn bản phù hợp trong cụm từ tìm kiếm của người dùng, ví dụ: như minh hoạ bên dưới.placeID
– Mã địa điểm của địa điểm được dự đoán. Mã địa điểm là giá trị nhận dạng dạng văn bản xác định riêng biệt một địa điểm. Để biết thêm thông tin về mã địa điểm, hãy xem bài viết Tổng quan về mã địa điểm.distanceMeters
– Khoảng cách theo đường thẳng từorigin
đã chỉ định đến điểm đến. Nếu bạn không đặt thuộc tínhorigin
, thì sẽ không có giá trị khoảng cách nào được trả về.
Ví dụ về mã sau đây minh hoạ cách làm nổi bật bằng chữ in đậm những phần của kết quả khớp với văn bản trong cụm từ tìm kiếm của người dùng, bằng cách sử dụng 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;
Sử dụng trình tìm nạp
Nếu muốn tự xây dựng chế độ kiểm soát tính năng tự động hoàn thành từ đầu, bạn có thể sử dụng GMSAutocompleteFetcher
. Chế độ này bao bọc phương thức autocompleteQuery
trên GMSPlacesClient
. Trình tìm nạp điều tiết các yêu cầu, chỉ trả về kết quả cho văn bản tìm kiếm được nhập gần đây nhất. Lớp này không cung cấp thành phần giao diện người dùng nào.
Để triển khai GMSAutocompleteFetcher
, hãy thực hiện các bước sau:
- Triển khai giao thức
GMSAutocompleteFetcherDelegate
. - Tạo một đối tượng
GMSAutocompleteFetcher
. - Gọi
sourceTextHasChanged
trên trình tìm nạp khi người dùng nhập. - Xử lý các dự đoán và lỗi bằng cách sử dụng các phương thức giao thức
didAutcompleteWithPredictions
vàdidFailAutocompleteWithError
.
Ví dụ về mã sau đây minh hoạ cách sử dụng trình tìm nạp để lấy thông tin đầu vào của người dùng và hiển thị các kết quả trùng khớp về địa điểm trong một khung hiển thị văn bản. Đã bỏ qua chức năng chọn địa điểm. FetcherSampleViewController
bắt nguồn từ UIViewController
trong 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
Mã thông báo phiên
Mã thông báo phiên nhóm các giai đoạn truy vấn và lựa chọn của một cụm từ tìm kiếm tự động hoàn thành của người dùng thành một phiên riêng biệt cho mục đích thanh toán. Phiên bắt đầu khi người dùng bắt đầu nhập một cụm từ tìm kiếm và kết thúc khi họ chọn một địa điểm. Mỗi phiên có thể có nhiều cụm từ tìm kiếm, theo sau là một lựa chọn địa điểm. Sau khi một phiên kết thúc, mã thông báo sẽ không còn hợp lệ; ứng dụng của bạn phải tạo một mã thông báo mới cho mỗi phiên. Bạn nên sử dụng mã thông báo phiên cho tất cả các phiên tự động hoàn thành theo chương trình (khi bạn sử dụng bộ điều khiển toàn màn hình hoặc bộ điều khiển kết quả, API sẽ tự động xử lý việc này).
Places SDK for iOS sử dụng GMSAutocompleteSessionToken
để xác định từng phiên. Ứng dụng của bạn phải truyền một mã thông báo phiên mới khi bắt đầu mỗi phiên mới, sau đó truyền mã thông báo đó cùng với một Mã địa điểm trong lệnh gọi tiếp theo đến fetchPlacefromPlaceID:
để truy xuất Thông tin chi tiết về địa điểm cho địa điểm mà người dùng đã chọn.
Tìm hiểu thêm về mã thông báo phiên.
Hãy dùng mã sau đây để tạo mã thông báo phiên mới:
let token: GMSAutocompleteSessionToken = GMSAutocompleteSessionToken.init()
Hạn mức sử dụng
- Việc sử dụng phương thức
GMSPlacesClient findAutocompletePredictionsFromQuery
phải tuân theo hạn mức truy vấn theo cấp. Hãy xem tài liệu về giới hạn sử dụng.
Hiển thị thông tin ghi nhận quyền tác giả trong ứng dụng
- Nếu ứng dụng của bạn sử dụng dịch vụ tự động hoàn thành theo phương thức lập trình, thì giao diện người dùng của bạn phải hiển thị thông tin ghi công "Do Google cung cấp" hoặc xuất hiện trong một bản đồ có thương hiệu của Google.
- Nếu ứng dụng của bạn sử dụng chế độ kiểm soát giao diện người dùng tự động hoàn thành, thì bạn không cần làm gì thêm (theo mặc định, thông tin ghi nhận quyền tác giả bắt buộc sẽ xuất hiện).
- Nếu truy xuất và hiển thị thông tin bổ sung về địa điểm sau khi nhận địa điểm theo mã nhận dạng, bạn cũng phải hiển thị thông tin ghi nhận quyền sở hữu của bên thứ ba.
Để biết thêm thông tin, hãy xem tài liệu về phân bổ.
Kiểm soát chỉ báo hoạt động mạng
Để kiểm soát chỉ báo hoạt động mạng trong thanh trạng thái của ứng dụng, bạn phải triển khai các phương thức uỷ quyền không bắt buộc thích hợp cho lớp tự động hoàn thành mà bạn đang sử dụng, đồng thời tự bật và tắt chỉ báo mạng.
- Đối với
GMSAutocompleteViewController
, bạn phải triển khai các phương thức uỷ quyềndidRequestAutocompletePredictions:
vàdidUpdateAutocompletePredictions:
. - Đối với
GMSAutocompleteResultsViewController
, bạn phải triển khai các phương thức uỷ quyềndidRequestAutocompletePredictionsForResultsController:
vàdidUpdateAutocompletePredictionsForResultsController:
. - Đối với
GMSAutocompleteTableDataSource
, bạn phải triển khai các phương thức uỷ quyềndidRequestAutocompletePredictionsForTableDataSource:
vàdidUpdateAutocompletePredictionsForTableDataSource:
.
Bằng cách triển khai các phương thức này và đặt [UIApplication
sharedApplication].networkActivityIndicatorVisible
thành YES
và NO
tương ứng, thanh trạng thái sẽ khớp chính xác với giao diện người dùng tự động hoàn thành.
Giới hạn kết quả tự động hoàn thành
Bạn có thể đặt chế độ kiểm soát giao diện người dùng tự động hoàn thành để giới hạn kết quả trong một khu vực địa lý cụ thể và/hoặc lọc kết quả theo một hoặc nhiều loại địa điểm, hoặc theo một hoặc nhiều quốc gia cụ thể. Để hạn chế kết quả, bạn có thể làm như sau:
- Để ưu tiên (thiên vị) kết quả trong khu vực đã xác định, hãy đặt
locationBias
trênGMSAutocompleteFilter
(một số kết quả từ bên ngoài khu vực đã xác định vẫn có thể được trả về). Nếu bạn cũng đặtlocationRestriction
, thìlocationBias
sẽ bị bỏ qua. Để chỉ hiển thị (hạn chế) kết quả trong khu vực đã xác định, hãy đặt
locationRestriction
trênGMSAutocompleteFilter
(chỉ kết quả trong khu vực đã xác định sẽ được trả về).- Lưu ý: Quy định hạn chế này chỉ áp dụng cho toàn bộ tuyến đường, kết quả tổng hợp nằm ngoài ranh giới hình chữ nhật có thể được trả về dựa trên tuyến đường trùng lặp với vị trí hạn chế.
Để chỉ trả về những kết quả phù hợp với một loại địa điểm cụ thể, hãy đặt
types
trênGMSAutocompleteFilter
(ví dụ: việc chỉ định TypeFilter.ADDRESS sẽ khiến tiện ích chỉ trả về những kết quả có địa chỉ chính xác).Để chỉ trả về kết quả trong tối đa 5 quốc gia được chỉ định, hãy đặt
countries
trênGMSAutocompleteFilter
.
Thiên vị kết quả cho một khu vực cụ thể
Để ưu tiên (thiên vị) kết quả trong khu vực đã xác định, hãy đặt locationBias
trên GMSAutocompleteFilter
, như minh hoạ ở đây:
northEast = CLLocationCoordinate2DMake(39.0, -95.0); southWest =
CLLocationCoordinate2DMake(37.5, -100.0); GMSAutocompleteFilter *filter =
[[GMSAutocompleteFilter alloc] init]; filter.locationBias =
GMSPlaceRectangularLocationOption(northEast, southWest);
Hạn chế kết quả ở một khu vực cụ thể
Để chỉ hiển thị (hạn chế) kết quả trong khu vực đã xác định, hãy đặt locationRestriction
trên GMSAutocompleteFilter
, như minh hoạ ở đây:
northEast = CLLocationCoordinate2DMake(39.0, -95.0); southWest =
CLLocationCoordinate2DMake(37.5, -100.0); GMSAutocompleteFilter *filter =
[[GMSAutocompleteFilter alloc] init]; filter.locationRestriction =
GMSPlaceRectangularLocationOption(northEast, southWest);
Lọc kết quả theo quốc gia
Để lọc kết quả trong tối đa 5 quốc gia được chỉ định, hãy đặt countries
trên GMSAutocompleteFilter
, như minh hoạ ở đây:
GMSAutocompleteFilter *filter = [[GMSAutocompleteFilter alloc] init];
filter.countries = @[ @"au", @"nz" ];
Lọc kết quả theo loại địa điểm hoặc loại bộ sưu tập
Hạn chế kết quả ở một loại hoặc tập hợp loại nhất định bằng cách đặt thuộc tính types
của GMSAutoCompleteFilter
.
Sử dụng thuộc tính này để chỉ định các bộ lọc được liệt kê trong Bảng 1, 2 và 3 trên PlaceTypes. Nếu bạn không chỉ định gì, thì tất cả các loại sẽ được trả về.
Cách chỉ định bộ lọc loại hoặc bộ lọc tập hợp loại:
Sử dụng thuộc tính
types
để chỉ định tối đa 5 giá trị type trong Bảng 1 và Bảng 2 xuất hiện trên Các loại địa điểm. Các giá trị loại được xác định bằng các hằng số trongGMSPlaceType
.Sử dụng thuộc tính
types
để chỉ định một type collection trong Bảng 3 xuất hiện trên Place Types (Các loại địa điểm). Các giá trị của tập hợp loại được xác định bằng các hằng số trongGMSPlaceType
.Bạn chỉ được phép dùng một loại trong Bảng 3 trong yêu cầu. Nếu chỉ định một giá trị trong Bảng 3, bạn không thể chỉ định một giá trị trong Bảng 1 hoặc Bảng 2. Nếu bạn làm như vậy, thì sẽ xảy ra lỗi.
Ví dụ: để chỉ trả về những kết quả phù hợp với một loại địa điểm cụ thể, hãy đặt types
trên GMSAutocompleteFilter
. Ví dụ sau đây cho thấy cách đặt bộ lọc để chỉ trả về kết quả có địa chỉ chính xác:
GMSAutocompleteFilter *filter = [[GMSAutocompleteFilter alloc] init];
filter.types = @[ kGMSPlaceTypeAirport, kGMSPlaceTypeAmusementPark ];
Tối ưu hoá tính năng Place Autocomplete (Cũ)
Phần này mô tả các phương pháp hay nhất giúp bạn khai thác tối đa dịch vụ Place Autocomplete (Cũ).
Dưới đây là một số nguyên tắc chung:
- Cách nhanh nhất để phát triển giao diện người dùng hoạt động là sử dụng tiện ích Tự động hoàn thành địa điểm (Cũ) của Maps JavaScript API, tiện ích Tự động hoàn thành địa điểm (Cũ) của Places SDK cho Android hoặc thành phần kiểm soát giao diện người dùng Tự động hoàn thành địa điểm (Cũ) của Places SDK cho iOS
- Ngay từ đầu, hãy tìm hiểu về các trường dữ liệu cần thiết của tính năng Tự động hoàn thành địa điểm (Phiên bản cũ).
- Các trường thiên vị vị trí và hạn chế vị trí là không bắt buộc nhưng có thể ảnh hưởng đáng kể đến hiệu suất tự động hoàn thành.
- Sử dụng tính năng xử lý lỗi để đảm bảo ứng dụng của bạn giảm hiệu suất một cách thích hợp nếu API trả về lỗi.
- Đảm bảo ứng dụng của bạn xử lý khi không có lựa chọn nào và cung cấp cho người dùng cách để tiếp tục.
Các phương pháp hay nhất để tối ưu hoá chi phí
Tối ưu hoá chi phí cơ bản
Để tối ưu hoá chi phí sử dụng dịch vụ Tự động hoàn thành địa điểm (Cũ), hãy sử dụng mặt nạ trường trong các tiện ích Chi tiết về địa điểm (Cũ) và Tự động hoàn thành địa điểm (Cũ) để chỉ trả về các trường dữ liệu về địa điểm mà bạn cần.
Tối ưu hoá chi phí nâng cao
Hãy cân nhắc việc triển khai theo chương trình tính năng Tự động hoàn thành địa điểm (Cũ) để truy cập vào mức giá Theo yêu cầu và yêu cầu kết quả Geocoding API về địa điểm đã chọn thay vì Chi tiết về địa điểm (Cũ). Mức giá Theo yêu cầu kết hợp với Geocoding API sẽ tiết kiệm chi phí hơn so với mức giá Theo phiên (dựa trên phiên) nếu cả hai điều kiện sau đều được đáp ứng:
- Nếu bạn chỉ cần vĩ độ/kinh độ hoặc địa chỉ của địa điểm mà người dùng đã chọn, thì Geocoding API sẽ cung cấp thông tin này cho ít hơn một lệnh gọi Place Details (Legacy).
- Nếu người dùng chọn một cụm từ gợi ý tự động hoàn thành trong trung bình 4 yêu cầu gợi ý tự động hoàn thành địa điểm (phiên bản cũ) hoặc ít hơn, thì mức giá Theo yêu cầu có thể tiết kiệm chi phí hơn so với mức giá Theo phiên.
Ứng dụng của bạn có yêu cầu thông tin nào khác ngoài địa chỉ và vĩ độ/kinh độ của kết quả dự đoán đã chọn không?
Có, cần thêm thông tin chi tiết
Sử dụng tính năng Place Autocomplete dựa trên phiên (Cũ) cùng với tính năng Place Details (Cũ).
Vì ứng dụng của bạn yêu cầu có Thông tin về địa điểm (cũ) như tên địa điểm, trạng thái kinh doanh hoặc giờ hoạt động, nên việc triển khai tính năng Tự động hoàn thành địa điểm (cũ) phải sử dụng mã thông báo phiên (theo phương pháp có lập trình hoặc được tích hợp vào các tiện ích JavaScript, Android hoặc iOS). mỗi phiên cộng với SKU Dữ liệu về địa điểm hiện hành, tuỳ thuộc vào những trường dữ liệu về địa điểm mà bạn yêu cầu.1
Triển khai tiện ích
Tính năng quản lý phiên được tự động tích hợp vào các tiện ích JavaScript, Android hoặc iOS. Điều này bao gồm cả yêu cầu Place Autocomplete (Cũ) và yêu cầu Place Details (Cũ) đối với cụm từ gợi ý đã chọn. Hãy nhớ chỉ định tham số fields
để đảm bảo bạn chỉ yêu cầu các trường dữ liệu về địa điểm mà bạn cần.
Triển khai theo chương trình
Sử dụng mã thông báo phiên với các yêu cầu Place Autocomplete (Cũ). Khi yêu cầu Thông tin chi tiết về địa điểm (Phiên bản cũ) về kết quả dự đoán đã chọn, hãy thêm các tham số sau:
- Mã địa điểm trong phản hồi Place Autocomplete (Cũ)
- Mã thông báo phiên được dùng trong yêu cầu Place Autocomplete (Cũ)
- Tham số
fields
chỉ định các trường dữ liệu về địa điểm mà bạn cần
Không, chỉ cần địa chỉ và vị trí
Geocoding API có thể là một lựa chọn tiết kiệm chi phí hơn so với Place Details (Legacy) cho ứng dụng của bạn, tuỳ thuộc vào hiệu suất của việc sử dụng Place Autocomplete (Legacy). Mức độ hiệu quả của tính năng Tự động hoàn thành địa điểm (Phiên bản cũ) của mỗi ứng dụng sẽ khác nhau, tuỳ thuộc vào nội dung mà người dùng nhập, vị trí sử dụng ứng dụng và việc bạn có triển khai các phương pháp hay nhất để tối ưu hoá hiệu suất hay không.
Để trả lời câu hỏi sau, hãy phân tích số lượng ký tự trung bình mà người dùng nhập trước khi chọn một kết quả dự đoán của tính năng Tự động hoàn thành địa điểm (Phiên bản cũ) trong ứng dụng của bạn.
Trung bình, người dùng của bạn có chọn một kết quả dự đoán của tính năng Tự động hoàn thành địa điểm (Phiên bản cũ) trong tối đa 4 yêu cầu không?
Có
Triển khai chương trình Place Autocomplete (Legacy) theo phương thức lập trình mà không cần mã thông báo phiên và gọi Geocoding API trên kết quả dự đoán địa điểm đã chọn.
Geocoding API cung cấp địa chỉ và toạ độ vĩ độ/kinh độ. Thực hiện 4 yêu cầu Place Autocomplete (Legacy) – Per Request (Tự động hoàn thành địa điểm (phiên bản cũ) – Theo yêu cầu) cộng với một lệnh gọi Geocoding API (Geocoding API) về cụm từ gợi ý địa điểm đã chọn sẽ ít tốn kém hơn so với chi phí Place Autocomplete (Legacy) (Tự động hoàn thành địa điểm (phiên bản cũ)) theo mỗi phiên.1
Hãy cân nhắc áp dụng các phương pháp hay nhất về hiệu suất để giúp người dùng nhận được thông tin dự đoán mà họ đang tìm kiếm chỉ trong vài ký tự.
Không
Sử dụng tính năng Place Autocomplete dựa trên phiên (Cũ) cùng với tính năng Place Details (Cũ).
Vì số lượng yêu cầu trung bình mà bạn dự kiến thực hiện trước khi người dùng chọn một kết quả dự đoán của tính năng Tự động hoàn thành địa điểm (Cũ) vượt quá chi phí của mức giá Theo phiên, nên việc triển khai tính năng Tự động hoàn thành địa điểm (Cũ) của bạn phải sử dụng mã thông báo phiên cho cả yêu cầu Tự động hoàn thành địa điểm (Cũ) và yêu cầu Chi tiết về địa điểm (Cũ) được liên kết cho mỗi phiên.1
Triển khai tiện ích
Tính năng quản lý phiên được tự động tích hợp vào các tiện ích JavaScript, Android hoặc iOS. Điều này bao gồm cả yêu cầu Place Autocomplete (Cũ) và yêu cầu Place Details (Cũ) đối với cụm từ gợi ý đã chọn. Hãy nhớ chỉ định tham số fields
để đảm bảo bạn chỉ yêu cầu các trường Dữ liệu cơ bản.
Triển khai theo chương trình
Sử dụng mã thông báo phiên với các yêu cầu Place Autocomplete (Cũ). Khi yêu cầu Thông tin chi tiết về địa điểm (Phiên bản cũ) về kết quả dự đoán đã chọn, hãy thêm các tham số sau:
- Mã địa điểm trong phản hồi Place Autocomplete (Cũ)
- Mã thông báo phiên được dùng trong yêu cầu Place Autocomplete (Cũ)
- Tham số
fields
chỉ định các trường Dữ liệu cơ bản, chẳng hạn như địa chỉ và hình học
Cân nhắc trì hoãn các yêu cầu về tính năng Tự động hoàn thành địa điểm (phiên bản cũ)
Bạn có thể áp dụng các chiến lược như trì hoãn yêu cầu về tính năng Tự động hoàn thành địa điểm (phiên bản cũ) cho đến khi người dùng nhập 3 hoặc 4 ký tự đầu tiên để ứng dụng của bạn đưa ra ít yêu cầu hơn. Ví dụ: việc đưa ra yêu cầu cho tính năng Tự động hoàn thành địa điểm (Phiên bản cũ) cho mỗi ký tự sau khi người dùng nhập ký tự thứ ba có nghĩa là nếu người dùng nhập 7 ký tự rồi chọn một cụm từ dự đoán mà bạn đưa ra một yêu cầu Geocoding API, thì tổng chi phí sẽ là 4 yêu cầu Tự động hoàn thành địa điểm (Phiên bản cũ) + Geocoding.1
Nếu việc trì hoãn các yêu cầu có thể giúp yêu cầu trung bình theo chương trình của bạn dưới 4, thì bạn có thể làm theo hướng dẫn để triển khai tính năng Place Autocomplete (Cũ) hiệu quả bằng Geocoding API. Xin lưu ý rằng người dùng có thể coi việc trì hoãn các yêu cầu là độ trễ. Họ có thể mong đợi nhìn thấy các cụm từ dự đoán sau mỗi lần nhấn phím mới.
Hãy cân nhắc việc áp dụng các phương pháp hay nhất về hiệu suất để giúp người dùng nhận được thông tin dự đoán mà họ đang tìm kiếm chỉ bằng ít ký tự hơn.
-
Để biết chi phí, hãy xem danh sách giá của Nền tảng Google Maps.
Các phương pháp hay nhất về hiệu suất
Các nguyên tắc sau đây mô tả những cách tối ưu hoá hiệu suất của tính năng Tự động hoàn thành địa điểm (Phiên bản cũ):
- Thêm các quy định hạn chế về quốc gia, độ lệch vị trí và (đối với các cách triển khai theo chương trình) lựa chọn ưu tiên về ngôn ngữ vào cách triển khai tính năng Tự động hoàn thành địa điểm (Phiên bản cũ). Không cần lựa chọn ưu tiên về ngôn ngữ đối với các tiện ích vì chúng chọn lựa chọn ưu tiên về ngôn ngữ từ trình duyệt hoặc thiết bị di động của người dùng.
- Nếu Place Autocomplete (Legacy) đi kèm với bản đồ, bạn có thể điều chỉnh vị trí theo khung hiển thị bản đồ.
- Trong trường hợp người dùng không chọn một trong các kết quả dự đoán của tính năng Tự động hoàn thành địa điểm (phiên bản cũ), thường là do không có kết quả dự đoán nào là địa chỉ mà họ muốn, bạn có thể sử dụng lại thông tin đầu vào ban đầu của người dùng để cố gắng nhận được kết quả phù hợp hơn:
- Nếu bạn chỉ muốn người dùng nhập thông tin địa chỉ, hãy sử dụng lại thông tin đầu vào ban đầu của người dùng trong một lệnh gọi đến Geocoding API.
- Nếu bạn muốn người dùng nhập cụm từ tìm kiếm cho một địa điểm cụ thể theo tên hoặc địa chỉ, hãy sử dụng yêu cầu Tìm địa điểm (Phiên bản cũ). Nếu chỉ mong đợi kết quả ở một khu vực cụ thể, hãy sử dụng thiên vị vị trí.
- Người dùng nhập địa chỉ của cơ sở phụ, chẳng hạn như địa chỉ của các căn hộ hoặc đơn vị cụ thể trong một toà nhà. Ví dụ: địa chỉ "Stroupežnického 3191/17, Praha" của Cộng hoà Séc sẽ cho ra một cụm từ gợi ý một phần trong tính năng Tự động hoàn thành địa điểm (phiên bản cũ).
- Người dùng nhập địa chỉ có tiền tố đoạn đường như "23-30 29th St, Queens" ở Thành phố New York hoặc "47-380 Kamehameha Hwy, Kaneohe" trên đảo Kauai ở Hawaii.
Khắc phục sự cố
Mặc dù có thể xảy ra nhiều loại lỗi, nhưng phần lớn các lỗi mà ứng dụng của bạn có thể gặp phải thường là do lỗi cấu hình (ví dụ: bạn đã sử dụng sai khoá API hoặc khoá API được định cấu hình không chính xác) hoặc lỗi hạn mức (ứng dụng của bạn đã vượt quá hạn mức). Hãy xem phần Giới hạn sử dụng để biết thêm thông tin về hạn mức.
Các lỗi xảy ra khi sử dụng chế độ tự động hoàn thành sẽ được trả về trong phương thức didFailAutocompleteWithError()
của nhiều giao thức uỷ quyền. Thuộc tính code
của đối tượng NSError
được cung cấp được đặt thành một trong các giá trị của phép liệt kê GMSPlacesErrorCode
.