Select Current Place and Show Details on a Map
This tutorial shows you how to build an iOS app to:
- Get the current device location.
- Get a list of places where the device is likely to be located.
- Prompt the user for the best place match.
- Show a marker on the map.
Follow this tutorial to build an iOS app using the Places API for iOS, the Maps SDK for iOS, and the Apple Core Location framework.
Get the code
Clone or download the Google Maps iOS samples repository from GitHub.Set up your development project

Follow these steps to install the Google Places API for iOS and the Google Maps SDK for iOS:
- Download and install Xcode.
- If you don't already have the CocoaPods tool, install it on macOS by
running the following command from the terminal:
sudo gem install cocoapods
- Clone or download the Google Maps iOS Tutorials repository.
- Navigate to the
current-place-on-mapdirectory. - Run the
pod installcommand. This installs the APIs specified in thePodfile, along with any dependencies they may have. - Open current-place-on-map.xcworkspace in Xcode.
For detailed installation instructions, see Getting Started (Maps), and Getting Started (Places).
Get an API key and enable the necessary APIs
To complete this tutorial, you need a Google API key that's authorized to use the Google Maps SDK for iOS and the Google Places API for iOS. Click the button below to get a key and activate the APIs.
Get a KeyFor more details, see Get an API key (Maps) , and Get an API key (Places).
Add the API key to your application
Add your API key to your AppDelegate.swift as follows:
- Add the following import statements:
import GooglePlaces import GoogleMaps
- Add the following to your
application(_:didFinishLaunchingWithOptions:)method, replacing YOUR_API_KEY with your API key:GMSPlacesClient.provideAPIKey("YOUR_API_KEY") GMSServices.provideAPIKey("YOUR_API_KEY")
Build and run your app
- Connect an iOS device to your computer, or select a simulator from the Xcode scheme pop-up menu.
- If you're using a device, make sure that location services are enabled. If you're using a simulator, select a location from the Debug/Location menu.
- In Xcode, click the Product/Run menu option (or the play button icon).
Xcode builds the app, and then runs the app on the device or on the simulator.
You should see a map with a number of markers centered around your current location, similar to the image on this page.
Troubleshooting:
- If you don't see a map, check that you've obtained an API key and added it to the app, as described above. Check Xcode's debugging console for error messages about the API key.
- The map will not display properly if the permissions request for
location services is declined.
- If you're using a device, go to Settings/General/Privacy/Location Services, and re-enable location services.
- If you're using a simulator, go to Simulator/Reset Content and Settings...
- Ensure that you have a good WiFi or GPS connection.
- If the app launches but no map is displayed, make sure that you have updated the Info.plist for your project with the appropriate location permissions. For more information about permissions handling, see the guide to requesting location permission in your app below.
- Use the Xcode debugging tools to view logs and debug the app.
Understand the code
This part of the tutorial explains the most significant parts of the current-place-on-map app, to help you understand how to build a similar app.
The current-place-on-map app features two view controllers:
One to display a map showing the user's currently selected place, and one
to present the user with a list of likely places to choose from. Note that
each view controller has the same variables for tracking the list of
likely places (likelyPlaces), and for indicating the user's
selection (selectedPlace). Navigation between views is
accomplished by using segues.
Request location permission
Your app must prompt the user for consent to use location services. To do
this, include the NSLocationAlwaysUsageDescription key in the
Info.plist file for the app, and set the value of each key to a
string that describes how the app intends to use location data.
Set up the location manager
Use CLLocationManager to find the device's current location and to request regular updates when the device moves to a new location. This tutorial provides the code you need to get the device's location. For more details, see the guide to Getting the User's Location in the Apple Developer Documentation.
- Declare the location manager, current location, map view, places client, and default zoom level at the class level.
- Initialize the location manager and
GMSPlacesClientinviewDidLoad(). - Declare variables to hold the list of likely places, and the user's selected place.
- Add delegates to handle events for the location manager, using an extension clause.
var locationManager = CLLocationManager() var currentLocation: CLLocation? var mapView: GMSMapView! var placesClient: GMSPlacesClient! var zoomLevel: Float = 15.0
locationManager = CLLocationManager() locationManager.desiredAccuracy = kCLLocationAccuracyBest locationManager.requestAlwaysAuthorization() locationManager.distanceFilter = 50 locationManager.startUpdatingLocation() locationManager.delegate = self placesClient = GMSPlacesClient.shared()
// An array to hold the list of likely places. var likelyPlaces: [GMSPlace] = [] // The currently selected place. var selectedPlace: GMSPlace?
extension MapViewController: CLLocationManagerDelegate {
// Handle incoming location events.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location: CLLocation = locations.last!
print("Location: \(location)")
let camera = GMSCameraPosition.camera(withLatitude: location.coordinate.latitude,
longitude: location.coordinate.longitude,
zoom: zoomLevel)
if mapView.isHidden {
mapView.isHidden = false
mapView.camera = camera
} else {
mapView.animate(to: camera)
}
listLikelyPlaces()
}
// Handle authorization for the location manager.
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .restricted:
print("Location access was restricted.")
case .denied:
print("User denied access to location.")
// Display the map using the default location.
mapView.isHidden = false
case .notDetermined:
print("Location status not determined.")
case .authorizedAlways: fallthrough
case .authorizedWhenInUse:
print("Location status is OK.")
}
}
// Handle location manager errors.
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
locationManager.stopUpdatingLocation()
print("Error: \(error)")
}
}
Add a map
- Create a map and add it to the view in
viewDidLoad()in the main view controller. The map stays hidden until a location update is received (location updates are handled in theCLLocationManagerDelegateextension).
let camera = GMSCameraPosition.camera(withLatitude: defaultLocation.coordinate.latitude,
longitude: defaultLocation.coordinate.longitude,
zoom: zoomLevel)
mapView = GMSMapView.map(withFrame: view.bounds, camera: camera)
mapView.settings.myLocationButton = true
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
//mapView.isMyLocationEnabled = true
// Add the map to the view, hide it until we've got a location update.
view.addSubview(mapView)
mapView.isHidden = true
Prompt the user to select their current place
Use the Places API for iOS to get the top five place
likelihoods based on the user's current location, and present the list in a
UITableView. When the user selects a place, add a marker to the
map.
- Get a list of likely places to populate a
UITableView, from which the user can select the place where they are currently located. - Open a new view to present likely places to the user. When the user
taps "Get Place", we segue to a new view, and show the user a list of possible
places to choose from. The
preparefunction updatesPlacesViewControllerwith the list of current likely places, and is automatically called when a segue is performed. - In
PlacesViewController, fill the table using the list of most likely places, using theUITableViewDataSourcedelegate extension. - Handle the user's selection using the
UITableViewDelegatedelegate extension.
// Populate the array with the list of likely places.
func listLikelyPlaces() {
// Clean up from previous sessions.
likelyPlaces.removeAll()
placesClient.currentPlace(callback: { (placeLikelihoods, error) -> Void in
if let error = error {
// TODO: Handle the error.
print("Current Place error: \(error.localizedDescription)")
return
}
// Get likely places and add to the list.
if let likelihoodList = placeLikelihoods {
for likelihood in likelihoodList.likelihoods {
let place = likelihood.place
self.likelyPlaces.append(place)
}
}
})
}
// Prepare the segue.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueToSelect" {
if let nextViewController = segue.destination as? PlacesViewController {
nextViewController.likelyPlaces = likelyPlaces
}
}
}
// Populate the table with the list of most likely places.
extension PlacesViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return likelyPlaces.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath)
let collectionItem = likelyPlaces[indexPath.row]
cell.textLabel?.text = collectionItem.name
return cell
}
// Show only the first five items in the table (scrolling is disabled in IB).
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return self.tableView.frame.size.height/5
}
// Make table rows display at proper height if there are less than 5 items.
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
if (section == tableView.numberOfSections - 1) {
return 1
}
return 0
}
}
class PlacesViewController: UIViewController {
...
// Pass the selected place to the new view controller.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "unwindToMain" {
if let nextViewController = segue.destination as? MapViewController {
nextViewController.selectedPlace = selectedPlace
}
}
}
}
...
// Respond when the user selects a place.
extension PlacesViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedPlace = likelyPlaces[indexPath.row]
performSegue(withIdentifier: "unwindToMain", sender: self)
}
}
Add a marker to the map
- When the user makes a selection, use an unwind segue to return to the
previous view, and add the marker to the map. The
unwindToMainIBAction is called automatically upon returning to the main view controller.
// Update the map once the user has made their selection.
@IBAction func unwindToMain(segue: UIStoryboardSegue) {
// Clear the map.
mapView.clear()
// Add a marker to the map.
if selectedPlace != nil {
let marker = GMSMarker(position: (self.selectedPlace?.coordinate)!)
marker.title = selectedPlace?.name
marker.snippet = selectedPlace?.formattedAddress
marker.map = mapView
}
listLikelyPlaces()
}
Congratulations! You've built an iOS app that lets the user choose their current place, and shows the result on a Google map. In the course of doing this, you've learned how to use the Places API for iOS, the Maps SDK for iOS, and the Apple Core Location framework.
Next steps
Learn about the place picker, a UI widget that displays an interactive map and a list of nearby places for the user to choose from.
