Place Autocomplete

Deprecation notices

Notice:TheinitWithBounds:filtermethod is deprecated as ofv3.10.0, and is unsupported inv4.0.0 and higher.Instead, useinitWithFilter:inGMSAutocompleteFetcher.h.Learn more.

Notice:ThesetAutocompleteBoundsUsingNorthEastCorner:SouthWestCorner helpermethod inGMSAutocompleteViewController,GMSAutocompleteResultsViewController,andGMSAutocompleteTableDataSource,is deprecated as of v3.10.0, and is unsupported inv4.0.0 and higher.Instead, uselocationBias,orlocationRestriction.Learn more.

Notice: The propertiesGMSAutocompleteViewController.autocompleteBounds andGMSAutocompleteViewController.autocompleteBoundsMode are deprecated as of v3.9.0, and are unsupported in v4.0.0 and higher. For equivalent functionality, useGMSAutocompleteViewController.filter, with eitherGMSAutocompleteFilter.locationBias orGMSAutocompleteFilter.locationRestriction.

Notice: The parametersbounds andboundsMode forfindAutocompletePredictionsFromQuery:bounds:boundsMode:filter:SessionToken:callback,autocompleteQuery:bounds:boundsMode:filter:callback, andautocompleteQuery:bounds:boundsMode:filter:callback are deprecated as of v3.9.0, and are unsupported in v4.0.0 and higher. For equivalent functionality, usefindAutocompletePredictionsFromQuery:filter:sessionToken:callback with eitherGMSAutocompleteFilter.locationBias orGMSAutocompleteFilter.locationRestriction.

The autocomplete service in the Places SDK for iOS returns placepredictions in response to user search queries. As the user types, theautocomplete service returns suggestions for places such as businesses,addresses,plus codesand points of interest.

You can add autocomplete to your app in the following ways:

Adding an autocomplete UI control

The autocomplete UI control is a search dialog with built-in autocompletefunctionality. As a user enters search terms, the control presents a list ofpredicted places to choose from. When the user makes a selection, aGMSPlaceinstance is returned, which your app can then use to get details about theselected place.

You can add the autocomplete UI control to your app in the following ways:

Adding a full-screen control

Use the full-screen control when you want a modal context, where theautocomplete UI temporarily replaces the UI of your app until the user has madetheir selection. This functionality is provided by theGMSAutocompleteViewControllerclass. When the user selects a place, your app receives a callback.

To add a full-screen control to your app:

  1. Create a UI element in your main app to launch the autocomplete UI control,for example a touch handler on aUIButton.
  2. Implement theGMSAutocompleteViewControllerDelegateprotocol in the parent view controller.
  3. Create an instance ofGMSAutocompleteViewControllerand assign the parent view controller as the delegate property.
  4. Create aGMSPlaceFieldto define the place data types to return.
  5. Add aGMSAutocompleteFilterto constrain the query to a particulartype of place.
  6. Present theGMSAutocompleteViewControllerusing[self presentViewController...].
  7. Handle the user's selection in thedidAutocompleteWithPlace delegatemethod.
  8. Dismiss the controller in thedidAutocompleteWithPlace,didFailAutocompleteWithError, andwasCancelled delegate methods.

The following example demonstrates one possible way to launchGMSAutocompleteViewControllerin response to the user tapping on a button.

Swift

importUIKitimportGooglePlacesclassViewController:UIViewController{overridefuncviewDidLoad(){makeButton()}// Present the Autocomplete view controller when the button is pressed.@objcfuncautocompleteClicked(_sender:UIButton){letautocompleteController=GMSAutocompleteViewController()autocompleteController.delegate=self// Specify the place data types to return.letfields:GMSPlaceField=GMSPlaceField(rawValue:UInt(GMSPlaceField.name.rawValue)|UInt(GMSPlaceField.placeID.rawValue))!autocompleteController.placeFields=fields// Specify a filter.letfilter=GMSAutocompleteFilter()filter.types=[.address]autocompleteController.autocompleteFilter=filter// Display the autocomplete view controller.present(autocompleteController,animated:true,completion:nil)}// Add a button to the view.funcmakeButton(){letbtnLaunchAc=UIButton(frame:CGRect(x:5,y:150,width:300,height:35))btnLaunchAc.backgroundColor=.bluebtnLaunchAc.setTitle("Launch autocomplete",for:.normal)btnLaunchAc.addTarget(self,action:#selector(autocompleteClicked),for:.touchUpInside)self.view.addSubview(btnLaunchAc)}}extensionViewController:GMSAutocompleteViewControllerDelegate{// Handle the user's selection.funcviewController(_viewController:GMSAutocompleteViewController,didAutocompleteWithplace:GMSPlace){print("Place name:\(place.name)")print("Place ID:\(place.placeID)")print("Place attributions:\(place.attributions)")dismiss(animated:true,completion:nil)}funcviewController(_viewController:GMSAutocompleteViewController,didFailAutocompleteWithErrorerror:Error){// TODO: handle the error.print("Error: ",error.localizedDescription)}// User canceled the operation.funcwasCancelled(_viewController:GMSAutocompleteViewController){dismiss(animated:true,completion:nil)}// Turn the network activity indicator on and off again.funcdidRequestAutocompletePredictions(_viewController:GMSAutocompleteViewController){UIApplication.shared.isNetworkActivityIndicatorVisible=true}funcdidUpdateAutocompletePredictions(_viewController:GMSAutocompleteViewController){UIApplication.shared.isNetworkActivityIndicatorVisible=false}}

Objective-C

#import "ViewController.h"@importGooglePlaces;@interfaceViewController()<GMSAutocompleteViewControllerDelegate>@end@implementationViewController{GMSAutocompleteFilter*_filter;}-(void)viewDidLoad{[superviewDidLoad];[selfmakeButton];}// Present the autocomplete view controller when the button is pressed.-(void)autocompleteClicked{GMSAutocompleteViewController*acController=[[GMSAutocompleteViewControlleralloc]init];acController.delegate=self;// Specify the place data types to return.GMSPlaceFieldfields=(GMSPlaceFieldName|GMSPlaceFieldPlaceID);acController.placeFields=fields;// Specify a filter._filter=[[GMSAutocompleteFilteralloc]init];_filter.types=@[kGMSPlaceTypeBank];acController.autocompleteFilter=_filter;// Display the autocomplete view controller.[selfpresentViewController:acControlleranimated:YEScompletion:nil];}// Add a button to the view.-(void)makeButton{UIButton*btnLaunchAc=[UIButtonbuttonWithType:UIButtonTypeCustom];[btnLaunchAcaddTarget:selfaction:@selector(autocompleteClicked)forControlEvents:UIControlEventTouchUpInside];[btnLaunchAcsetTitle:@"Launch autocomplete"forState:UIControlStateNormal];btnLaunchAc.frame=CGRectMake(5.0,150.0,300.0,35.0);btnLaunchAc.backgroundColor=[UIColorblueColor];[self.viewaddSubview:btnLaunchAc];}// Handle the user's selection.-(void)viewController:(GMSAutocompleteViewController*)viewControllerdidAutocompleteWithPlace:(GMSPlace*)place{[selfdismissViewControllerAnimated:YEScompletion: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*)viewControllerdidFailAutocompleteWithError:(NSError*)error{[selfdismissViewControllerAnimated:YEScompletion:nil];// TODO: handle the error.NSLog(@"Error: %@",[errordescription]);}// User canceled the operation.-(void)wasCancelled:(GMSAutocompleteViewController*)viewController{[selfdismissViewControllerAnimated:YEScompletion:nil];}// Turn the network activity indicator on and off again.-(void)didRequestAutocompletePredictions:(GMSAutocompleteViewController*)viewController{[UIApplicationsharedApplication].networkActivityIndicatorVisible=YES;}-(void)didUpdateAutocompletePredictions:(GMSAutocompleteViewController*)viewController{[UIApplicationsharedApplication].networkActivityIndicatorVisible=NO;}@end

Adding a results controller

Use a results controller when you want more control over the text input UI. Theresults controller dynamically toggles the visibility of the results list basedon input UI focus.

To add a results controller to your app:

  1. Create aGMSAutocompleteResultsViewController.
    1. Implement theGMSAutocompleteResultsViewControllerDelegateprotocol in the parent view controller and assign the parent view controller asthe delegate property.
  2. Create aUISearchController object, passing in theGMSAutocompleteResultsViewControlleras the results controller argument.
  3. Set theGMSAutocompleteResultsViewControlleras thesearchResultsUpdater property of theUISearchController.
  4. Add thesearchBar for theUISearchController to your app's UI.
  5. Handle the user's selection in thedidAutocompleteWithPlace delegatemethod.

There are several ways to place the search bar of aUISearchController intoyour app's UI:

Adding a search bar to the navigation bar

The following code example demonstrates adding a results controller, adding thesearchBar to the navigation bar, and handling the user's selection:

Swift

classViewController:UIViewController{varresultsViewController:GMSAutocompleteResultsViewController?varsearchController:UISearchController?varresultView:UITextView?overridefuncviewDidLoad(){super.viewDidLoad()resultsViewController=GMSAutocompleteResultsViewController()resultsViewController?.delegate=selfsearchController=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.extensionViewController:GMSAutocompleteResultsViewControllerDelegate{funcresultsController(_resultsController:GMSAutocompleteResultsViewController,didAutocompleteWithplace: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)")}funcresultsController(_resultsController:GMSAutocompleteResultsViewController,didFailAutocompleteWithErrorerror:Error){// TODO: handle the error.print("Error: ",error.localizedDescription)}// Turn the network activity indicator on and off again.funcdidRequestAutocompletePredictions(_viewController:GMSAutocompleteViewController){UIApplication.shared.isNetworkActivityIndicatorVisible=true}funcdidUpdateAutocompletePredictions(_viewController:GMSAutocompleteViewController){UIApplication.shared.isNetworkActivityIndicatorVisible=false}}

Objective-C

-(void)viewDidLoad{_resultsViewController=[[GMSAutocompleteResultsViewControlleralloc]init];_resultsViewController.delegate=self;_searchController=[[UISearchControlleralloc]initWithSearchResultsController:_resultsViewController];_searchController.searchResultsUpdater=_resultsViewController;// Put the search bar in the navigation bar.[_searchController.searchBarsizeToFit];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*)resultsControllerdidAutocompleteWithPlace:(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*)resultsControllerdidFailAutocompleteWithError:(NSError*)error{[selfdismissViewControllerAnimated:YEScompletion:nil];// TODO: handle the error.NSLog(@"Error: %@",[errordescription]);}// Turn the network activity indicator on and off again.-(void)didRequestAutocompletePredictionsForResultsController:(GMSAutocompleteResultsViewController*)resultsController{[UIApplicationsharedApplication].networkActivityIndicatorVisible=YES;}-(void)didUpdateAutocompletePredictionsForResultsController:(GMSAutocompleteResultsViewController*)resultsController{[UIApplicationsharedApplication].networkActivityIndicatorVisible=NO;}
Note: For the search bar to display properly, your app's view controller must beenclosed within aUINavigationController.

Adding a search bar to the top of a view

The following code example shows adding thesearchBar to the top of a view.

Swift

importUIKitimportGooglePlacesclassViewController:UIViewController{varresultsViewController:GMSAutocompleteResultsViewController?varsearchController:UISearchController?varresultView:UITextView?overridefuncviewDidLoad(){super.viewDidLoad()resultsViewController=GMSAutocompleteResultsViewController()resultsViewController?.delegate=selfsearchController=UISearchController(searchResultsController:resultsViewController)searchController?.searchResultsUpdater=resultsViewControllerletsubView=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.extensionViewController:GMSAutocompleteResultsViewControllerDelegate{funcresultsController(_resultsController:GMSAutocompleteResultsViewController,didAutocompleteWithplace: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)")}funcresultsController(_resultsController:GMSAutocompleteResultsViewController,didFailAutocompleteWithErrorerror:Error){// TODO: handle the error.print("Error: ",error.localizedDescription)}// Turn the network activity indicator on and off again.funcdidRequestAutocompletePredictions(forResultsControllerresultsController:GMSAutocompleteResultsViewController){UIApplication.shared.isNetworkActivityIndicatorVisible=true}funcdidUpdateAutocompletePredictions(forResultsControllerresultsController:GMSAutocompleteResultsViewController){UIApplication.shared.isNetworkActivityIndicatorVisible=false}}

Objective-C

-(void)viewDidLoad{[superviewDidLoad];_resultsViewController=[[GMSAutocompleteResultsViewControlleralloc]init];_resultsViewController.delegate=self;_searchController=[[UISearchControlleralloc]initWithSearchResultsController:_resultsViewController];_searchController.searchResultsUpdater=_resultsViewController;UIView*subView=[[UIViewalloc]initWithFrame:CGRectMake(0,65.0,250,50)];[subViewaddSubview:_searchController.searchBar];[_searchController.searchBarsizeToFit];[self.viewaddSubview: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*)resultsControllerdidAutocompleteWithPlace:(GMSPlace*)place{[selfdismissViewControllerAnimated:YEScompletion: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*)resultsControllerdidFailAutocompleteWithError:(NSError*)error{[selfdismissViewControllerAnimated:YEScompletion:nil];// TODO: handle the error.NSLog(@"Error: %@",[errordescription]);}// Turn the network activity indicator on and off again.-(void)didRequestAutocompletePredictionsForResultsController:(GMSAutocompleteResultsViewController*)resultsController{[UIApplicationsharedApplication].networkActivityIndicatorVisible=YES;}-(void)didUpdateAutocompletePredictionsForResultsController:(GMSAutocompleteResultsViewController*)resultsController{[UIApplicationsharedApplication].networkActivityIndicatorVisible=NO;}

By default,UISearchController hides the navigation bar when presenting (this can be disabled). In cases wherethe navigation bar is visible and opaque,UISearchController does not set theplacement correctly.

Use the following code as a workaround:

Swift

navigationController?.navigationBar.translucent=falsesearchController?.hidesNavigationBarDuringPresentation=false// This makes the view area include the nav bar even though it is opaque.// Adjust the view placement down.self.extendedLayoutIncludesOpaqueBars=trueself.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;

Adding a search bar using popover results

The following code example shows placing a search bar on the right side of thenavigation bar, and displaying results in a popover.

Caution:Popovers will only appear on iPad, and on the iPhone 6+ in landscape mode. Onall other devices this will fallback to a fullscreen view controller.

Swift

importUIKitimportGooglePlacesclassViewController:UIViewController{varresultsViewController:GMSAutocompleteResultsViewController?varsearchController:UISearchController?varresultView:UITextView?overridefuncviewDidLoad(){super.viewDidLoad()resultsViewController=GMSAutocompleteResultsViewController()resultsViewController?.delegate=selfsearchController=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=falsesearchController?.modalPresentationStyle=.popover}}// Handle the user's selection.extensionViewController:GMSAutocompleteResultsViewControllerDelegate{funcresultsController(_resultsController:GMSAutocompleteResultsViewController,didAutocompleteWithplace: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)")}funcresultsController(_resultsController:GMSAutocompleteResultsViewController,didFailAutocompleteWithErrorerror:Error){// TODO: handle the error.print("Error: ",error.localizedDescription)}// Turn the network activity indicator on and off again.funcdidRequestAutocompletePredictions(forResultsControllerresultsController:GMSAutocompleteResultsViewController){UIApplication.shared.isNetworkActivityIndicatorVisible=true}funcdidUpdateAutocompletePredictions(forResultsControllerresultsController:GMSAutocompleteResultsViewController){UIApplication.shared.isNetworkActivityIndicatorVisible=false}}

Objective-C

-(void)viewDidLoad{[superviewDidLoad];_resultsViewController=[[GMSAutocompleteResultsViewControlleralloc]init];_resultsViewController.delegate=self;_searchController=[[UISearchControlleralloc]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=[[UIBarButtonItemalloc]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*)resultsControllerdidAutocompleteWithPlace:(GMSPlace*)place{[selfdismissViewControllerAnimated:YEScompletion:nil];NSLog(@"Place name %@",place.name);NSLog(@"Place address %@",place.formattedAddress);NSLog(@"Place attributions %@",place.attributions.string);}-(void)resultsController:(GMSAutocompleteResultsViewController*)resultsControllerdidFailAutocompleteWithError:(NSError*)error{[selfdismissViewControllerAnimated:YEScompletion:nil];// TODO: handle the error.NSLog(@"Error: %@",[errordescription]);}// Turn the network activity indicator on and off again.-(void)didRequestAutocompletePredictionsForResultsController:(GMSAutocompleteResultsViewController*)resultsController{[UIApplicationsharedApplication].networkActivityIndicatorVisible=YES;}-(void)didUpdateAutocompletePredictionsForResultsController:(GMSAutocompleteResultsViewController*)resultsController{[UIApplicationsharedApplication].networkActivityIndicatorVisible=NO;}
Note: For the search bar to display properly, your app's view controller must beenclosed within aUINavigationController.

Using a table data source

If your app has a custom search text UI, you can use theGMSAutocompleteTableDataSourceclass to drive the table view displaying the results on the view controller.

To useGMSAutocompleteTableDataSourceas the data source and delegate of theUITableView in a view controller:

  1. Implement theGMSAutocompleteTableDataSourceDelegateandUISearchBarDelegate protocols in the view controller.
  2. Create aGMSAutocompleteTableDataSourceinstance and assign the view controller as the delegate property.
  3. Set theGMSAutocompleteTableDataSourceas the datasource and delegate properties of theUITableView instance on the view controller.
  4. In the handler for the search text input, callsourceTextHasChanged on theGMSAutocompleteTableDataSource.
    1. Handle the user's selection in thedidAutocompleteWithPlace delegatemethod.
  5. Dismiss the controller in thedidAutocompleteWithPlace,didFailAutocompleteWithError,wasCancelled delegate methods.

The following code example demonstrates using theGMSAutocompleteTableDataSource class to drive the table view of aUIViewController when theUISearchBar isadded separately.

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.importGooglePlacesimportUIKitclassPlaceAutocompleteViewController:UIViewController{privatevartableView:UITableView!privatevartableDataSource:GMSAutocompleteTableDataSource!overridefuncviewDidLoad(){super.viewDidLoad()letsearchBar=UISearchBar(frame:CGRect(x:0,y:20,width:self.view.frame.size.width,height:44.0))searchBar.delegate=selfview.addSubview(searchBar)tableDataSource=GMSAutocompleteTableDataSource()tableDataSource.delegate=selftableView=UITableView(frame:CGRect(x:0,y:64,width:self.view.frame.size.width,height:self.view.frame.size.height-44))tableView.delegate=tableDataSourcetableView.dataSource=tableDataSourceview.addSubview(tableView)}}extensionPlaceAutocompleteViewController:UISearchBarDelegate{funcsearchBar(_searchBar:UISearchBar,textDidChangesearchText:String){// Update the GMSAutocompleteTableDataSource with the search text.tableDataSource.sourceTextHasChanged(searchText)}}extensionPlaceAutocompleteViewController:GMSAutocompleteTableDataSourceDelegate{funcdidUpdateAutocompletePredictions(fortableDataSource:GMSAutocompleteTableDataSource){// Turn the network activity indicator off.UIApplication.shared.isNetworkActivityIndicatorVisible=false// Reload table data.tableView.reloadData()}funcdidRequestAutocompletePredictions(fortableDataSource:GMSAutocompleteTableDataSource){// Turn the network activity indicator on.UIApplication.shared.isNetworkActivityIndicatorVisible=true// Reload table data.tableView.reloadData()}functableDataSource(_tableDataSource:GMSAutocompleteTableDataSource,didAutocompleteWithplace:GMSPlace){// Do something with the selected place.print("Place name:\(place.name)")print("Place address:\(place.formattedAddress)")print("Place attributions:\(place.attributions)")}functableDataSource(_tableDataSource:GMSAutocompleteTableDataSource,didFailAutocompleteWithErrorerror:Error){// Handle the error.print("Error:\(error.localizedDescription)")}functableDataSource(_tableDataSource:GMSAutocompleteTableDataSource,didSelectprediction:GMSAutocompletePrediction)->Bool{returntrue}}

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"@importGooglePlaces;@importUIKit;@interfacePlaceAutocompleteViewController()<GMSAutocompleteTableDataSourceDelegate,UISearchBarDelegate>@end@implementationPlaceAutocompleteViewController{UITableView*tableView;GMSAutocompleteTableDataSource*tableDataSource;}-(void)viewDidLoad{[superviewDidLoad];UISearchBar*searchBar=[[UISearchBaralloc]initWithFrame:CGRectMake(0,20,self.view.frame.size.width,44)];searchBar.delegate=self;[self.viewaddSubview:searchBar];tableDataSource=[[GMSAutocompleteTableDataSourcealloc]init];tableDataSource.delegate=self;tableView=[[UITableViewalloc]initWithFrame:CGRectMake(0,64,self.view.frame.size.width,self.view.frame.size.height-44)];tableView.delegate=tableDataSource;tableView.dataSource=tableDataSource;[self.viewaddSubview:tableView];}#pragma mark - GMSAutocompleteTableDataSourceDelegate-(void)didUpdateAutocompletePredictionsForTableDataSource:(GMSAutocompleteTableDataSource*)tableDataSource{// Turn the network activity indicator off.UIApplication.sharedApplication.networkActivityIndicatorVisible=NO;// Reload table data.[tableViewreloadData];}-(void)didRequestAutocompletePredictionsForTableDataSource:(GMSAutocompleteTableDataSource*)tableDataSource{// Turn the network activity indicator on.UIApplication.sharedApplication.networkActivityIndicatorVisible=YES;// Reload table data.[tableViewreloadData];}-(void)tableDataSource:(GMSAutocompleteTableDataSource*)tableDataSourcedidAutocompleteWithPlace:(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*)tableDataSourcedidFailAutocompleteWithError:(NSError*)error{// Handle the errorNSLog(@"Error %@",error.description);}-(BOOL)tableDataSource:(GMSAutocompleteTableDataSource*)tableDataSourcedidSelectPrediction:(GMSAutocompletePrediction*)prediction{returnYES;}#pragma mark - UISearchBarDelegate-(void)searchBar:(UISearchBar*)searchBartextDidChange:(NSString*)searchText{// Update the GMSAutocompleteTableDataSource with the search text.[tableDataSourcesourceTextHasChanged:searchText];}@end

Customizing text and background colors

You can set the colors of all text and backgrounds in the autocomplete UIcontrol, to make the widget match the visual appearance of your app moreclosely. There are two ways to set the UI control colors:

  • By using the built-in iOSUIAppearanceprotocol to globally style UI controls where possible. These settings apply to many,but not all, of the UI control elements.
  • By using the SDK methods on the widget classes to set properties which arenot supported by theUIAppearanceprotocol.

Typically, your app will use some combination of theUIAppearanceprotocol and the SDK methods. The following diagram shows which elements can be styled:

Autocomplete UI control colors

The following table lists all of the UI elements, and indicates how each oneshould be styled (UIAppearance protocol or SDK method).

UI ElementMethodHow to style
Navigation Bar tint (background)UIAppearance protocolCallsetBarTintColor onUINavigationBar proxy.
Navigation Bar tint color (search bar text caret and Cancel button)UIAppearance protocolCallsetTintColor onUINavigationBar proxy.
Search Bar text colorUIAppearance protocolSetNSForegroundColorAttributeName insearchBarTextAttributes.
Search bar tint colorN/AThe search bar is translucent, and will display as a shaded version of the Navigation Bar.
Search bar placeholder text color (default search text)UIAppearance protocolSetNSForegroundColorAttributeName inplaceholderAttributes.
Primary text (also applied to error and message text)SDK methodCallprimaryTextColor.
Primary text highlightSDK methodCallprimaryTextHighlightColor.
Secondary textSDK methodCallsecondaryTextColor.
Error and message textSDK methodCallprimaryTextColor.
Table cell backgroundSDK methodCalltableCellBackgroundColor.
Table cell separator colorSDK methodCalltableCellSeparatorColor.
"Try Again" buttonSDK methodCalltintColor.
Activity indicator (progress spinner)UIAppearance protocolCallsetColor onUIActivityIndicatorView proxy.
"Powered by Google" logo, Sad cloud imageN/AWhite or gray version is automatically selected based on background contrast.
Magnifying glass and clear text icons in Search Bar text fieldN/ATo style, replace the default images with images of the desired color.
Note: These properties only affect the color settings of UI elements. Changingthe size of UI elements, or the font used in table cells, is not supported.

Using the UIAppearance protocol

You can use theUIAppearanceprotocol to get the appearance proxy for a given UI element, which you can then use toset the color for the UI element. When a modification is made, all instances ofa given UI element are affected. For example, the following example globallychanges the text color ofUITextField classes to green when they are containedin aUISearchBar:

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

For more information about defining color values, consult theUIColor ClassReference.

The following code snippets show all of the proxy commands you need to use tostyle everything in the full-screen autocomplete UI control. Add this code tothedidFinishLaunchingWithOptions method in Appdelegate.m:

// Define some colors.UIColor*darkGray=[UIColordarkGrayColor];UIColor*lightGray=[UIColorlightGrayColor];// Navigation bar background.[[UINavigationBarappearance]setBarTintColor:darkGray];[[UINavigationBarappearance]setTintColor:lightGray];// Color of typed text in the search bar.NSDictionary*searchBarTextAttributes=@{NSForegroundColorAttributeName:lightGray,NSFontAttributeName:[UIFontsystemFontOfSize:[UIFontsystemFontSize]]};[UITextFieldappearanceWhenContainedInInstancesOfClasses:@[[UISearchBarclass]]].defaultTextAttributes=searchBarTextAttributes;// Color of the placeholder text in the search bar prior to text entry.NSDictionary*placeholderAttributes=@{NSForegroundColorAttributeName:lightGray,NSFontAttributeName:[UIFontsystemFontOfSize:[UIFontsystemFontSize]]};// Color of the default search text.// NOTE: In a production scenario, "Search" would be a localized string.NSAttributedString*attributedPlaceholder=[[NSAttributedStringalloc]initWithString:@"Search"attributes:placeholderAttributes];[UITextFieldappearanceWhenContainedInInstancesOfClasses:@[[UISearchBarclass]]].attributedPlaceholder=attributedPlaceholder;// Color of the in-progress spinner.[[UIActivityIndicatorViewappearance]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.[[UISearchBarappearance]setImage:[UIImageimageNamed:@"custom_clear_x_high"]forSearchBarIcon:UISearchBarIconClearstate:UIControlStateHighlighted];[[UISearchBarappearance]setImage:[UIImageimageNamed:@"custom_clear_x"]forSearchBarIcon:UISearchBarIconClearstate:UIControlStateNormal];[[UISearchBarappearance]setImage:[UIImageimageNamed:@"custom_search"]forSearchBarIcon:UISearchBarIconSearchstate:UIControlStateNormal];// Color of selected table cells.UIView*selectedBackgroundView=[[UIViewalloc]init];selectedBackgroundView.backgroundColor=[UIColorlightGrayColor];[UITableViewCellappearanceWhenContainedIn:[GMSAutocompleteViewControllerclass],nil].selectedBackgroundView=selectedBackgroundView;

Setting UI control style properties

A subset of UI control elements have properties that are not affected by theUIAppearance protocol, and so must be set directly. The following code exampleshows defining foreground and background colors, and applying them to a UIcontrol instance namedacController. Add this code to theonLaunchClickedmethod in ViewController.m:

UIColor*darkGray=[UIColordarkGrayColor];UIColor*lightGray=[UIColorlightGrayColor];acController.secondaryTextColor=[UIColorcolorWithWhite:1.0falpha:0.5f];acController.primaryTextColor=lightGray;acController.primaryTextHighlightColor=[UIColorgrayColor];acController.tableCellBackgroundColor=darkGray;acController.tableCellSeparatorColor=lightGray;acController.tintColor=lightGray;
Note: ForGMSAutocompleteViewController andGMSAutocompleteResultsViewController, you can use Interface Builder to setthese values.

Getting place predictions programmatically

You can create a custom search UI as an alternative to the UI provided by theautocomplete widget. To do this, your app must get place predictionsprogrammatically. Your app can get a list of predicted place names and/oraddresses in one of the following ways:

CallingGMSPlacesClient findAutocompletePredictionsFromQuery:

To get a list of predicted place names and/or addresses, firstinstantiateGMSPlacesClient,then call theGMSPlacesClientfindAutocompletePredictionsFromQuery:method with the following parameters:

  • AnautocompleteQuery string containing the text typed by the user.
  • AGMSAutocompleteSessionToken,which is used to identify each individual session. Your app should pass thesame token for each autocomplete request call, then pass that token, alongwith a Place ID, in the subsequent call tofetchPlacefromPlaceID:to retrieve Place Details for the place that was selected by the user.
  • AGMSAutocompleteFilterto:
    • Bias or restrict the results to a specific region.
    • Restrict the results to a specifictype of place.
    • AGMSPlaceLocationBias/Restriction object biasing the results to aspecific area specified by latitude and longitude bounds.
  • A callback method to handle the returned predictions.

The code examples below show a call tofindAutocompletePredictionsFromQuery:.

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. */lettoken=GMSAutocompleteSessionToken.init()// Create a type filter.letfilter=GMSAutocompleteFilter()filter.types=[.bank]filter.locationBias=GMSPlaceRectangularLocationOption(northEastBounds,southWestBounds);placesClient?.findAutocompletePredictions(fromQuery:"cheesebu",filter:filter,sessionToken:token,callback:{(results,error)inifleterror=error{print("Autocomplete error:\(error)")return}ifletresults=results{forresultinresults{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=[[GMSAutocompleteSessionTokenalloc]init];// Create a type filter.GMSAutocompleteFilter*_filter=[[GMSAutocompleteFilteralloc]init];_filter.types=@[kGMSPlaceTypeBank];[_placesClientfindAutocompletePredictionsFromQuery:@"cheesebu"filter:_filtersessionToken:tokencallback:^(NSArray<GMSAutocompletePrediction*>*_Nullableresults,NSError*_Nullableerror){if(error!=nil){NSLog(@"An error occurred %@",[errorlocalizedDescription]);return;}if(results!=nil){for(GMSAutocompletePrediction*resultinresults){NSLog(@"Result %@ with PlaceID %@",result.attributedFullText,result.placeID);}}}];

The API invokes the specified callback method, passing in an array ofGMSAutocompletePredictionobjects.

EachGMSAutocompletePredictionobject contains the following information:

  • attributedFullText – The full text of the prediction, in the form ofanNSAttributedString. For example, 'Sydney Opera House, Sydney, New SouthWales, Australia'. Every text range that matches the user input has anattribute,kGMSAutocompleteMatchAttribute. You can use this attribute tohighlight the matching text in the user's query, for example, as shownbelow.
  • placeID – The place ID of the predicted place. A place ID is atextual identifier that uniquely identifies a place. For more informationabout place IDs, see thePlace IDoverview.
  • distanceMeters – The straight-line distance from the specifiedorigin to the destination. If theorigin property is not set, nodistance value will be returned.

The following code example illustrates how to highlight in bold text the partsof the result that match text in the user's query, usingenumerateAttribute:

Swift

letregularFont=UIFont.systemFont(ofSize:UIFont.labelFontSize)letboldFont=UIFont.boldSystemFont(ofSize:UIFont.labelFontSize)letbolded=prediction.attributedFullText.mutableCopy()as!NSMutableAttributedStringbolded.enumerateAttribute(kGMSAutocompleteMatchAttribute,in:NSMakeRange(0,bolded.length),options:[]){(value,range:NSRange,stop:UnsafeMutablePointer<ObjCBool>)->Voidinletfont=(value==nil)?regularFont:boldFontbolded.addAttribute(NSFontAttributeName,value:font,range:range)}label.attributedText=bolded

Objective-C

UIFont*regularFont=[UIFontsystemFontOfSize:[UIFontlabelFontSize]];UIFont*boldFont=[UIFontboldSystemFontOfSize:[UIFontlabelFontSize]];NSMutableAttributedString*bolded=[prediction.attributedFullTextmutableCopy];[boldedenumerateAttribute:kGMSAutocompleteMatchAttributeinRange:NSMakeRange(0,bolded.length)options:0usingBlock:^(idvalue,NSRangerange,BOOL*stop){UIFont*font=(value==nil)?regularFont:boldFont;[boldedaddAttribute:NSFontAttributeNamevalue:fontrange:range];}];label.attributedText=bolded;

Using the fetcher

If you want to build your own autocomplete control from scratch, you can useGMSAutocompleteFetcher, whichwraps theautocompleteQuery method onGMSPlacesClient. The fetcherthrottles requests, returning only results for the most recently entered searchtext. It provides no UI elements.

To implementGMSAutocompleteFetcher,take the following steps:

  1. Implement theGMSAutocompleteFetcherDelegateprotocol.
  2. Create aGMSAutocompleteFetcherobject.
  3. CallsourceTextHasChanged on the fetcher as the user types.
  4. Handle predictions and errors using thedidAutcompleteWithPredictionsanddidFailAutocompleteWithErrorprotocol methods.

The following code example demonstrates using the fetcher to take user input anddisplay place matches in a text view. Functionality for selecting a place hasbeen omitted.FetcherSampleViewController derives fromUIViewController inFetcherSampleViewController.h.

Swift

importUIKitimportGooglePlacesclassViewController:UIViewController{vartextField:UITextField?varresultText:UITextView?varfetcher:GMSAutocompleteFetcher?overridefuncviewDidLoad(){super.viewDidLoad()view.backgroundColor=.whiteedgesForExtendedLayout=[]// Set bounds to inner-west Sydney Australia.letneBoundsCorner=CLLocationCoordinate2D(latitude:-33.843366,longitude:151.134002)letswBoundsCorner=CLLocationCoordinate2D(latitude:-33.875725,longitude:151.200349)// Set up the autocomplete filter.letfilter=GMSAutocompleteFilter()filter.locationRestriction=GMSPlaceRectangularLocationOption(neBoundsCorner,swBoundsCorner)// Create a new session token.lettoken:GMSAutocompleteSessionToken=GMSAutocompleteSessionToken.init()// Create the fetcher.fetcher=GMSAutocompleteFetcher(bounds:nil,filter:filter)fetcher?.delegate=selffetcher?.provide(token)textField=UITextField(frame:CGRect(x:5.0,y:10.0,width:view.bounds.size.width-5.0,height:64.0))textField?.autoresizingMask=.flexibleWidthtextField?.addTarget(self,action:#selector(textFieldDidChange(textField:)),for:.editingChanged)letplaceholder=NSAttributedString(string:"Type a query...")textField?.attributedPlaceholder=placeholderresultText=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=falseself.view.addSubview(textField!)self.view.addSubview(resultText!)}@objcfunctextFieldDidChange(textField:UITextField){fetcher?.sourceTextHasChanged(textField.text!)}}extensionViewController:GMSAutocompleteFetcherDelegate{funcdidAutocomplete(withpredictions:[GMSAutocompletePrediction]){letresultsStr=NSMutableString()forpredictioninpredictions{resultsStr.appendFormat("\n Primary text: %@\n",prediction.attributedPrimaryText)resultsStr.appendFormat("Place ID: %@\n",prediction.placeID)}resultText?.text=resultsStrasString}funcdidFailAutocompleteWithError(_error:Error){resultText?.text=error.localizedDescription}}

Objective-C

#import "FetcherSampleViewController.h"#import <GooglePlaces/GooglePlaces.h>@interfaceFetcherSampleViewController()<GMSAutocompleteFetcherDelegate>@end@implementationFetcherSampleViewController{UITextField*_textField;UITextView*_resultText;GMSAutocompleteFetcher*_fetcher;}-(void)viewDidLoad{[superviewDidLoad];self.view.backgroundColor=[UIColorwhiteColor];self.edgesForExtendedLayout=UIRectEdgeNone;// Set bounds to inner-west Sydney Australia.CLLocationCoordinate2DneBoundsCorner=CLLocationCoordinate2DMake(-33.843366,151.134002);CLLocationCoordinate2DswBoundsCorner=CLLocationCoordinate2DMake(-33.875725,151.200349);GMSAutocompleteFilter*autocompleteFilter=[[GMSAutocompleteFilteralloc]init];autocompleteFilter.locationRestriction=GMSPlaceRectangularLocationOption(neBoundsCorner,swBoundsCorner);// Create the fetcher._fetcher=[[GMSAutocompleteFetcheralloc]initWithBounds:nilfilter:filter];_fetcher.delegate=self;// Set up the UITextField and UITextView._textField=[[UITextFieldalloc]initWithFrame:CGRectMake(5.0f,0,self.view.bounds.size.width-5.0f,44.0f)];_textField.autoresizingMask=UIViewAutoresizingFlexibleWidth;[_textFieldaddTarget:selfaction:@selector(textFieldDidChange:)forControlEvents:UIControlEventEditingChanged];_resultText=[[UITextViewalloc]initWithFrame:CGRectMake(0,45.0f,self.view.bounds.size.width,self.view.bounds.size.height-45.0f)];_resultText.backgroundColor=[UIColorcolorWithWhite:0.95falpha:1.0f];_resultText.text=@"No Results";_resultText.editable=NO;[self.viewaddSubview:_textField];[self.viewaddSubview:_resultText];}-(void)textFieldDidChange:(UITextField*)textField{NSLog(@"%@",textField.text);[_fetchersourceTextHasChanged:textField.text];}#pragma mark - GMSAutocompleteFetcherDelegate-(void)didAutocompleteWithPredictions:(NSArray*)predictions{NSMutableString*resultsStr=[NSMutableStringstring];for(GMSAutocompletePrediction*predictioninpredictions){[resultsStrappendFormat:@"%@\n",[prediction.attributedPrimaryTextstring]];}_resultText.text=resultsStr;}-(void)didFailAutocompleteWithError:(NSError*)error{_resultText.text=[NSStringstringWithFormat:@"%@",error.localizedDescription];}@end

Session tokens

Session tokens group the query and selection phases of a user autocompletesearch into a discrete session for billing purposes. The session begins when theuser starts typing a query, and concludes when they select a place. Each sessioncan have multiple queries, followed by one place selection. Once a session hasconcluded, the token is no longer valid; your app must generate a fresh tokenfor each session. We recommend using session tokens for all programmaticautocomplete sessions (when you use the full-screen controller, or the resultscontroller, the API takes care of this automatically).

The Places SDK for iOS uses aGMSAutocompleteSessionTokento identify each session. Your app should pass a new session token uponbeginning each new session, then pass that same token, along with a Place ID, inthe subsequent call tofetchPlacefromPlaceID:to retrieve Place Details for the place that was selected by the user.

Tip: If your app is using theAutocompletewidget, youdon't need to implement sessions, as the widget handles sessions automaticallyin the background.

Learn more about sessiontokens.

Use the following code to generate a new session token:

let token: GMSAutocompleteSessionToken = GMSAutocompleteSessionToken.init()

Usage limits

Displaying attributions in your app

  • If your app uses the autocomplete service programmatically, your UI musteither display a 'Powered by Google' attribution, or appear within aGoogle-branded map.
  • If your app uses the autocomplete UI control no additional action isrequired (the required attribution is displayed by default).
  • If you retrieve and display additional place information aftergetting aplace by ID,you must display third-party attributions too.

For more details, see the documentation onattributions.

Controlling the network activity indicator

To control the network activity indicator in the applications status bar youmust implement the appropriate optional delegate methods for the autocompleteclass you are using and turn the network indicator on and off yourself.

  • ForGMSAutocompleteViewControlleryou must implement the delegate methodsdidRequestAutocompletePredictions:anddidUpdateAutocompletePredictions:.
  • ForGMSAutocompleteResultsViewControlleryou must implement the delegate methodsdidRequestAutocompletePredictionsForResultsController: anddidUpdateAutocompletePredictionsForResultsController:.
  • ForGMSAutocompleteTableDataSourceyou must implement the delegate methodsdidRequestAutocompletePredictionsForTableDataSource: anddidUpdateAutocompletePredictionsForTableDataSource:.

By implementing these methods and setting[UIApplicationsharedApplication].networkActivityIndicatorVisible toYES andNOrespectively the status bar will correctly match the autocomplete UI.

Constrain autocomplete results

You can set the autocomplete UI control to constrain results to a specificgeographic region, and/or filter the results to one or more place types, or to aspecific country or countries. To constrain results, you can do the following:

  • Toprefer (bias) results within the defined region, setlocationBias ontheGMSAutocompleteFilter (some results from outside the defined region maystill be returned). IflocationRestriction is also set,locationBiaswill be ignored.
  • Toonly show (restrict) results within the defined region, setlocationRestriction on theGMSAutocompleteFilter (only results withinthe defined region will be returned).

    • Note: This restriction is only applied to entire routes, syntheticresults located outside the rectangular bounds may be returned based ona route that overlaps with the location restrict.
  • To return only results that conform to a particular place type, settypeson theGMSAutocompleteFilter, (for example, specifying TypeFilter.ADDRESS willcause the widget to return only results with a precise address).

  • To return only results within up to five specified countries, setcountries on theGMSAutocompleteFilter.

Bias results to a specific region

Toprefer (bias) results within the defined region, setlocationBias on theGMSAutocompleteFilter, as shown here:

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

Restrict results to a specific region

Toonly show (restrict) results within the defined region, setlocationRestriction on theGMSAutocompleteFilter, as shown here:

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

Filter results by country

To filter results within up to five specified countries, setcountries on theGMSAutocompleteFilter, as shown here:

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

Filter results by place type or type collection

Restrict results to be of a certain type or type collection by setting thetypes property ofGMSAutoCompleteFilter.Use this property to specify filters listed in Tables 1, 2, and 3 onPlaceTypes. If nothing is specified, all types are returned.

To specify a type or type collection filter:

  • Use thetypes property to specify up to fivetype values from Table 1and Table 2 shown onPlace Types. The type values aredefined by the constants inGMSPlaceType.

  • Use thetypes property to specify atype collection from Table 3 shownonPlace Types. The type collection values are defined bythe constants inGMSPlaceType.

    Only a single type from Table 3 is allowed in the request. If you specify avalue from Table 3, you cannot specify a value from Table 1 or Table 2. Ifyou do, then an error occurs.

For example, to return only results that conform to a particular place type, settypes on theGMSAutocompleteFilter. The following example shows setting thefilter to return only results with a precise address:

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

Place Autocomplete (Legacy) optimization

This section describes best practices to help you make the most of the Place Autocomplete (Legacy) service.

Here are some general guidelines:

  • The quickest way to develop a working user interface is to use the Maps JavaScript APIPlace Autocomplete (Legacy) widget, Places SDK for AndroidPlace Autocomplete (Legacy) widget, or Places SDK for iOSPlace Autocomplete (Legacy) UI control
  • Develop an understanding of essential Place Autocomplete (Legacy)data fields from the start.
  • Location biasing and location restriction fields are optional but can have a significant impact on autocomplete performance.
  • Use error handling to make sure your app degrades gracefully if the API returns an error.
  • Make sure your app handles when there is no selection and offers users a way to continue.

Cost optimization best practices

Basic cost optimization

To optimize the cost of using the Place Autocomplete (Legacy) service, use field masks in Place Details (Legacy) and Place Autocomplete (Legacy) widgets to return only theplace data fields you need.

Advanced cost optimization

Consider programmatic implementation of Place Autocomplete (Legacy) in order to accessPer Request pricing and requestGeocoding API results about the selected place instead of Place Details (Legacy). Per Request pricing paired with Geocoding API is more cost-effective than Per Session (session-based) pricing if both of the following conditions are met:

  • If you only need the latitude/longitude or address of the user's selected place, the Geocoding API delivers this information for less than a Place Details (Legacy) call.
  • If users select an autocomplete prediction within an average of four Place Autocomplete (Legacy) predictions requests or fewer, Per Request pricing may be more cost-effective than Per Session pricing.
For help selecting the Place Autocomplete (Legacy) implementation that fits your needs, select the tab that corresponds to your answer to the following question.

Does your application require any information other than the address and latitude/longitude of the selected prediction?

Yes, needs more details

Use session-based Place Autocomplete (Legacy) with Place Details (Legacy).
Since your application requires Place Details (Legacy) such as the place name, business status, or opening hours, your implementation of Place Autocomplete (Legacy) should use a session token (programmatically or built into theJavaScript,Android, oriOS widgets).per session plus applicablePlaces Data SKUs depending on which place data fields you request.1

Widget implementation
Session management is automatically built into theJavaScript,Android, oriOS widgets. This includes both the Place Autocomplete (Legacy) requests and the Place Details (Legacy) request on the selected prediction. Be sure to specify thefields parameter in order to ensure you are only requesting theplace data fields you need.

Programmatic implementation
Use asession token with your Place Autocomplete (Legacy) requests. When requestingPlace Details (Legacy) about the selected prediction, include the following parameters:

  1. The place ID fromthe Place Autocomplete (Legacy) response
  2. The session token used in the Place Autocomplete (Legacy) request
  3. Thefields parameter specifying theplace data fields you need

No, needs only address and location

Geocoding API could be a more cost-effective option than Place Details (Legacy) for your application, depending on the performance of your Place Autocomplete (Legacy) usage. Every application's Place Autocomplete (Legacy) efficiency varies depending on what users are entering, where the application is being used, and whetherperformance optimization best practices have been implemented.

In order to answer the following question, analyze how many characters a user types on average before selecting a Place Autocomplete (Legacy) prediction in your application.

Do your users select a Place Autocomplete (Legacy) prediction in four or fewer requests, on average?

Yes

Implement Place Autocomplete (Legacy) programmatically without session tokens and call Geocoding API on the selected place prediction.
Geocoding API delivers addresses and latitude/longitude coordinates. Making fourPlace Autocomplete (Legacy) - Per Request requests plus aGeocoding API call about the selected place prediction is less than the Per Session Place Autocomplete (Legacy) cost per session.1

Consider employingperformance best practices to help your users get the prediction they're looking for in even fewer characters.

No

Use session-based Place Autocomplete (Legacy) with Place Details (Legacy).
Since the average number of requests you expect to make before a user selects a Place Autocomplete (Legacy) prediction exceeds the cost of Per Session pricing, your implementation of Place Autocomplete (Legacy) should use a session token for both the Place Autocomplete (Legacy) requests and the associated Place Details (Legacy) requestper session.1

Widget implementation
Session management is automatically built into theJavaScript,Android, oriOS widgets. This includes both the Place Autocomplete (Legacy) requests and the Place Details (Legacy) request on the selected prediction. Be sure to specify thefields parameter in order to ensure you are only requestingBasic Data fields.

Programmatic implementation
Use asession token with your Place Autocomplete (Legacy) requests. When requestingPlace Details (Legacy) about the selected prediction, include the following parameters:

  1. The place ID fromthe Place Autocomplete (Legacy) response
  2. The session token used in the Place Autocomplete (Legacy) request
  3. Thefields parameter specifyingBasic Data fields such as address and geometry

Consider delaying Place Autocomplete (Legacy) requests
You can employ strategies such as delaying a Place Autocomplete (Legacy) request until the user has typed in the first three or four characters so that your application makes fewer requests. For example, making Place Autocomplete (Legacy) requests for each characterafter the user has typed the third character means that if the user types seven characters then selects a prediction for which you make one Geocoding API request, the total cost would be for 4 Place Autocomplete (Legacy) Per Request + Geocoding.1

If delaying requests can get your average programmatic request below four, you can follow the guidance forperformant Place Autocomplete (Legacy) with Geocoding API implementation. Note that delaying requests can be perceived as latency by the user who might be expecting to see predictions with every new keystroke.

Consider employingperformance best practices to help your users get the prediction they're looking for in fewer characters.

Performance best practices

The following guidelines describe ways to optimize Place Autocomplete (Legacy) performance:

  • Add country restrictions,location biasing, and (for programmatic implementations) language preference to your Place Autocomplete (Legacy) implementation. Language preference is not needed with widgets since they pick language preferences from the user's browser or mobile device.
  • If Place Autocomplete (Legacy) is accompanied by a map, you can bias location by map viewport.
  • In situations when a user does not choose one of the Place Autocomplete (Legacy) predictions, generally because none of those predictions are the result-address wanted, you can reuse the original user input to attempt to get more relevant results:
    • If you expect the user to enter only address information, reuse the original user input in a call to theGeocoding API.
    • If you expect the user to enter queries for a specific place by name or address, use aFind Place (Legacy) request. If results are only expected in a specific region, uselocation biasing.
    Other scenarios when it's best to fall back to the Geocoding API include:
    • Users inputting subpremise addresses, such as addresses for specific units or apartments within a building. For example, the Czech address "Stroupežnického 3191/17, Praha" yields a partial prediction in Place Autocomplete (Legacy).
    • Users inputting addresses with road-segment prefixes like "23-30 29th St, Queens" in New York City or "47-380 Kamehameha Hwy, Kaneohe" on the island of Kauai in Hawai'i.

Troubleshooting

Although a wide variety of errors can occur, the majority of the errors your appis likely to experience are usually caused by configuration errors (for example,the wrong API key was used, or the API key was configured incorrectly), or quotaerrors (your app has exceeded its quota). SeeUsageLimits formore information about quotas.

Errors that occur in the use of the autocomplete controls are returned in thedidFailAutocompleteWithError() method of the various delegate protocols. Thecode property of the suppliedNSError object is set to one of the values oftheGMSPlacesErrorCode enumeration.

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-11-21 UTC.