Sélectionner le lieu actuel et afficher les détails sur une carte

Ce tutoriel explique comment créer une application iOS qui récupère la position actuelle de l'appareil, identifie les lieux possibles, invite l'utilisateur à sélectionner la meilleure correspondance et affiche un repère sur la carte. pour l'emplacement choisi.

Il convient aux personnes qui ont une connaissance débutant ou intermédiaire de Swift ou d'Objective-C et connaissances générales de Xcode. Pour en savoir plus sur pour créer des cartes, consultez les des développeurs guide de démarrage.

Vous allez créer la carte suivante à l'aide de ce tutoriel. Le repère sur la carte est positionné à San. Francisco, Californie, mais déménagera là où se trouve l'appareil ou le simulateur.

Ce tutoriel utilise la classe SDK Places pour iOS le SDK Maps pour iOS, et le framework Apple Core Location.

Obtenir le code

Cloner ou télécharger Dépôt d'exemples Google Maps pour iOS de GitHub.

Vous pouvez également cliquer sur le bouton suivant pour télécharger le code source:

Obtenir le code

MapViewController Swift

/*
 * Copyright 2016 Google Inc. All rights reserved.
 *
 *
 * 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 UIKit
import GoogleMaps
import GooglePlaces

class MapViewController: UIViewController {

  var locationManager: CLLocationManager!
  var currentLocation: CLLocation?
  var mapView: GMSMapView!
  var placesClient: GMSPlacesClient!
  var preciseLocationZoomLevel: Float = 15.0
  var approximateLocationZoomLevel: Float = 10.0

  // An array to hold the list of likely places.
  var likelyPlaces: [GMSPlace] = []

  // The currently selected place.
  var selectedPlace: GMSPlace?

  // 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 let place = selectedPlace {
      let marker = GMSMarker(position: place.coordinate)
      marker.title = selectedPlace?.name
      marker.snippet = selectedPlace?.formattedAddress
      marker.map = mapView
    }

    listLikelyPlaces()
  }

  override func viewDidLoad() {
    super.viewDidLoad()
    
    // Initialize the location manager.
    locationManager = CLLocationManager()
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.requestWhenInUseAuthorization()
    locationManager.distanceFilter = 50
    locationManager.startUpdatingLocation()
    locationManager.delegate = self

    placesClient = GMSPlacesClient.shared()

    // A default location to use when location permission is not granted.
    let defaultLocation = CLLocation(latitude: -33.869405, longitude: 151.199)
    
    // Create a map.
    let zoomLevel = locationManager.accuracyAuthorization == .fullAccuracy ? preciseLocationZoomLevel : approximateLocationZoomLevel
    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

    listLikelyPlaces()
  }

  // Populate the array with the list of likely places.
  func listLikelyPlaces() {
    // Clean up from previous sessions.
    likelyPlaces.removeAll()

    let placeFields: GMSPlaceField = [.name, .coordinate]
    placesClient.findPlaceLikelihoodsFromCurrentLocation(withPlaceFields: placeFields) { (placeLikelihoods, error) in
      guard error == nil else {
        // TODO: Handle the error.
        print("Current Place error: \(error!.localizedDescription)")
        return
      }

      guard let placeLikelihoods = placeLikelihoods else {
        print("No places found.")
        return
      }
      
      // Get likely places and add to the list.
      for likelihood in placeLikelihoods {
        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
      }
    }
  }
}

// Delegates to handle events for the location manager.
extension MapViewController: CLLocationManagerDelegate {

  // Handle incoming location events.
  func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    let location: CLLocation = locations.last!
    print("Location: \(location)")

    let zoomLevel = locationManager.accuracyAuthorization == .fullAccuracy ? preciseLocationZoomLevel : approximateLocationZoomLevel
    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) {
    // Check accuracy authorization
    let accuracy = manager.accuracyAuthorization
    switch accuracy {
    case .fullAccuracy:
        print("Location accuracy is precise.")
    case .reducedAccuracy:
        print("Location accuracy is not precise.")
    @unknown default:
      fatalError()
    }
    
    // Handle authorization status
    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.")
    @unknown default:
      fatalError()
    }
  }

  // Handle location manager errors.
  func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
    locationManager.stopUpdatingLocation()
    print("Error: \(error)")
  }
}

      

PlacesViewController Swift

/*
 * Copyright 2017 Google Inc. All rights reserved.
 *
 *
 * 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 UIKit
import GooglePlaces

class PlacesViewController: UIViewController {

  @IBOutlet weak var tableView: UITableView!

  // An array to hold the list of possible locations.
  var likelyPlaces: [GMSPlace] = []
  var selectedPlace: GMSPlace?

  // Cell reuse id (cells that scroll out of view can be reused).
  let cellReuseIdentifier = "cell"

  override func viewDidLoad() {
    super.viewDidLoad()

    // Register the table view cell class and its reuse id.
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)

    // This view controller provides delegate methods and row data for the table view.
    tableView.delegate = self
    tableView.dataSource = self

    tableView.reloadData()
  }

  // 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 a user selects a place.
extension PlacesViewController: UITableViewDelegate {
  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    selectedPlace = likelyPlaces[indexPath.row]
    performSegue(withIdentifier: "unwindToMain", sender: self)
  }

  // Adjust cell height to only show 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
  }
}

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

      

MapViewController Obj-C

//
//  MapsViewController.m
//  current-place-on-map
//
//  Created by Chris Arriola on 9/18/20.
//  Copyright © 2020 William French. All rights reserved.
//

#import "MapViewController.h"
#import "PlacesViewController.h"
@import CoreLocation;
@import GooglePlaces;
@import GoogleMaps;

@interface MapViewController () <CLLocationManagerDelegate>

@end

@implementation MapViewController {
  CLLocationManager *locationManager;
  CLLocation * _Nullable currentLocation;
  GMSMapView *mapView;
  GMSPlacesClient *placesClient;
  float preciseLocationZoomLevel;
  float approximateLocationZoomLevel;
  
  // An array to hold the list of likely places.
  NSMutableArray<GMSPlace *> *likelyPlaces;

  // The currently selected place.
  GMSPlace * _Nullable selectedPlace;
}

- (void)viewDidLoad {
  [super viewDidLoad];
  preciseLocationZoomLevel = 15.0;
  approximateLocationZoomLevel = 15.0;

  // Initialize the location manager.
  locationManager = [[CLLocationManager alloc] init];
  locationManager.desiredAccuracy = kCLLocationAccuracyBest;
  [locationManager requestWhenInUseAuthorization];
  locationManager.distanceFilter = 50;
  [locationManager startUpdatingLocation];
  locationManager.delegate = self;

  placesClient = [GMSPlacesClient sharedClient];

  // A default location to use when location permission is not granted.
  CLLocationCoordinate2D defaultLocation = CLLocationCoordinate2DMake(-33.869405, 151.199);
  
  // Create a map.
  float zoomLevel = locationManager.accuracyAuthorization == CLAccuracyAuthorizationFullAccuracy ? preciseLocationZoomLevel : approximateLocationZoomLevel;
  GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:defaultLocation.latitude
                                                          longitude:defaultLocation.longitude
                                                               zoom:zoomLevel];
  mapView = [GMSMapView mapWithFrame:self.view.bounds camera:camera];
  mapView.settings.myLocationButton = YES;
  mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  mapView.myLocationEnabled = YES;

  // Add the map to the view, hide it until we've got a location update.
  [self.view addSubview:mapView];
  mapView.hidden = YES;

  [self listLikelyPlaces];
}

// Populate the array with the list of likely places.
- (void) listLikelyPlaces
{
  // Clean up from previous sessions.
  likelyPlaces = [NSMutableArray array];

  GMSPlaceField placeFields = GMSPlaceFieldName | GMSPlaceFieldCoordinate;
  [placesClient findPlaceLikelihoodsFromCurrentLocationWithPlaceFields:placeFields callback:^(NSArray<GMSPlaceLikelihood *> * _Nullable likelihoods, NSError * _Nullable error) {
    if (error != nil) {
      // TODO: Handle the error.
      NSLog(@"Current Place error: %@", error.localizedDescription);
      return;
    }
    
    if (likelihoods == nil) {
      NSLog(@"No places found.");
      return;
    }
    
    for (GMSPlaceLikelihood *likelihood in likelihoods) {
      GMSPlace *place = likelihood.place;
      [likelyPlaces addObject:place];
    }
  }];
}

// Update the map once the user has made their selection.
- (void) unwindToMain:(UIStoryboardSegue *)segue
{
  // Clear the map.
  [mapView clear];

  // Add a marker to the map.
  if (selectedPlace != nil) {
    GMSMarker *marker = [GMSMarker markerWithPosition:selectedPlace.coordinate];
    marker.title = selectedPlace.name;
    marker.snippet = selectedPlace.formattedAddress;
    marker.map = mapView;
  }

  [self listLikelyPlaces];
}

// Prepare the segue.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
  if ([segue.identifier isEqualToString:@"segueToSelect"]) {
    if ([segue.destinationViewController isKindOfClass:[PlacesViewController class]]) {
      PlacesViewController *placesViewController = (PlacesViewController *)segue.destinationViewController;
      placesViewController.likelyPlaces = likelyPlaces;
    }
  }
}

// Delegates to handle events for the location manager.
#pragma mark - CLLocationManagerDelegate

// Handle incoming location events.
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
  CLLocation *location = locations.lastObject;
  NSLog(@"Location: %@", location);
  
  float zoomLevel = locationManager.accuracyAuthorization == CLAccuracyAuthorizationFullAccuracy ? preciseLocationZoomLevel : approximateLocationZoomLevel;
  GMSCameraPosition * camera = [GMSCameraPosition cameraWithLatitude:location.coordinate.latitude
                                                           longitude:location.coordinate.longitude
                                                                zoom:zoomLevel];
  
  if (mapView.isHidden) {
    mapView.hidden = NO;
    mapView.camera = camera;
  } else {
    [mapView animateToCameraPosition:camera];
  }

  [self listLikelyPlaces];
}

// Handle authorization for the location manager.
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
  // Check accuracy authorization
  CLAccuracyAuthorization accuracy = manager.accuracyAuthorization;
  switch (accuracy) {
    case CLAccuracyAuthorizationFullAccuracy:
      NSLog(@"Location accuracy is precise.");
      break;
    case CLAccuracyAuthorizationReducedAccuracy:
      NSLog(@"Location accuracy is not precise.");
      break;
  }
  
  // Handle authorization status
  switch (status) {
    case kCLAuthorizationStatusRestricted:
      NSLog(@"Location access was restricted.");
      break;
    case kCLAuthorizationStatusDenied:
      NSLog(@"User denied access to location.");
      // Display the map using the default location.
      mapView.hidden = NO;
    case kCLAuthorizationStatusNotDetermined:
      NSLog(@"Location status not determined.");
    case kCLAuthorizationStatusAuthorizedAlways:
    case kCLAuthorizationStatusAuthorizedWhenInUse:
      NSLog(@"Location status is OK.");
  }
}

// Handle location manager errors.
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
  [manager stopUpdatingLocation];
  NSLog(@"Error: %@", error.localizedDescription);
}

@end

      

Obj-C PlacesViewController

// 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 "PlacesViewController.h"

@interface PlacesViewController () <UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, weak) UITableView *tableView;
@end

@implementation PlacesViewController {
  // Cell reuse id (cells that scroll out of view can be reused).
  NSString *cellReuseIdentifier;
}

- (void)viewDidLoad {
  [super viewDidLoad];
  cellReuseIdentifier = @"cell";
}

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
  
}

#pragma mark - UITableViewDelegate

// Respond when a user selects a place.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
  self.selectedPlace = [self.likelyPlaces objectAtIndex:indexPath.row];
  [self performSegueWithIdentifier:@"unwindToMain" sender:self];
}

// Adjust cell height to only show the first five items in the table
// (scrolling is disabled in IB).
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
  return self.tableView.frame.size.height/5;
}

// Make table rows display at proper height if there are less than 5 items.
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
  if (section == tableView.numberOfSections - 1) {
    return 1;
  }
  return 0;
}

#pragma mark - UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
  return self.likelyPlaces.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  return [tableView dequeueReusableCellWithIdentifier:cellReuseIdentifier forIndexPath:indexPath];
}
@end

      

Commencer

Gestionnaire de paquets Swift

Le SDK Maps pour iOS peut être installé à l'aide du gestionnaire de packages Swift.

  1. Assurez-vous d'avoir supprimé toutes les dépendances existantes du SDK Maps pour iOS.
  2. Ouvrez une fenêtre de terminal et accédez au répertoire tutorials/current-place-on-map.
  3. Assurez-vous que votre espace de travail Xcode est fermé et exécutez les commandes suivantes:
    sudo gem install cocoapods-deintegrate cocoapods-clean
    pod deintegrate
    pod cache clean --all
    rm Podfile
    rm current-place-on-map.xcworkspace
  4. Ouvrez votre projet Xcode et supprimez le fichier Podfile.
  5. Ajoutez les SDK Places et Maps:
    1. Accédez à Fichier > Ajouter des dépendances de packages
    2. Saisissez https://github.com/googlemaps/ios-places-sdk. comme URL, appuyez sur Entrée pour récupérer le package, puis cliquez sur Ajouter un package.
    3. Saisissez https://github.com/googlemaps/ios-maps-sdk. comme URL, appuyez sur Entrée pour récupérer le package, puis cliquez sur Ajouter un package.
  6. Il se peut que vous deviez réinitialiser le cache du package en sélectionnant Fichier > Packages > Réinitialiser le cache du package

Utiliser CocoaPods

  1. Téléchargez et installez Xcode. version 15.0 ou ultérieure.
  2. Si vous ne possédez pas encore CocoaPods, Installez-le sur macOS en exécutant la commande suivante depuis le terminal:
    sudo gem install cocoapods
  3. Accédez au répertoire tutorials/current-place-on-map.
  4. Exécutez la commande pod install. Cette action installera les SDK Maps et Places spécifiés dans Podfile, ainsi que toutes les dépendances.
  5. Exécutez pod outdated pour comparer la version du pod installée avec les nouvelles mises à jour. Si une nouvelle version est détectée, exécutez pod update pour mettre à jour Podfile et installer la dernière version du SDK. Pour en savoir plus, consultez le guide CocoaPods.
  6. Ouvrez (double-cliquez) sur l'espace de travail current-place-on-map.xcworkspace du projet. pour l'ouvrir dans Xcode. Vous devez utiliser le fichier .xcworkspace pour ouvrir le projet.

Obtenir une clé API et activer les API nécessaires

Pour suivre ce tutoriel, vous devez disposer d'une clé API Google autorisée à utiliser le SDK Maps pour iOS et l'API Places.

  1. Suivez les instructions de la section Premiers pas avec Google Maps Platform pour configurer un compte de facturation et un projet pour lesquels ces deux produits sont activés.
  2. Suivez les instructions de la section Obtenir une clé API afin de créer une clé API pour le projet de développement que vous avez configuré précédemment.

Ajouter la clé API à votre application

Ajoutez votre clé API à votre fichier AppDelegate.swift comme suit :

  1. Notez que l'instruction d'importation suivante a été ajoutée au fichier:
    import GooglePlaces
    import GoogleMaps
  2. Modifiez la ligne suivante dans votre fichier application(_:didFinishLaunchingWithOptions:) , en remplaçant YOUR_API_KEY par votre clé API:
    GMSPlacesClient.provideAPIKey("YOUR_API_KEY")
    GMSServices.provideAPIKey("YOUR_API_KEY")

Compiler et exécuter votre application

  1. Connectez un appareil iOS à votre ordinateur, ou sélectionnez un simulateur dans le menu pop-up du schéma Xcode.
  2. Si vous utilisez un appareil, assurez-vous que les services de localisation sont activés. Si vous utilisez un simulateur, sélectionnez un lieu dans Fonctionnalités. .
  3. Dans Xcode, cliquez sur l'option de menu Product/Run (Produit/Exécuter) l'icône du bouton).
    • Xcode crée l'application, puis l'exécute sur l'appareil ou sur le de machine learning.
    • Vous devriez voir une carte avec un certain nombre de repères centrés autour de votre position actuelle l'emplacement.

Dépannage :

  • Si aucune carte ne s'affiche, vérifiez que vous avez bien obtenu une clé API et ajouté à l'application, comme décrit ci-dessus. Chèque Console de débogage de Xcode pour les messages d'erreur concernant la clé API.
  • Si vous avez restreint la clé API à l'aide de l'identifiant du bundle iOS, modifiez la pour ajouter l'identifiant de bundle pour l'application: com.google.examples.current-place-on-map
  • La carte ne s'affichera pas correctement si la demande d'autorisations service de localisation est refusé.
    • Si vous utilisez un appareil, accédez à Paramètres/Général/Confidentialité/Position Services, et réactivez les services de localisation.
    • Si vous utilisez un simulateur, accédez à la section Simulateur/Réinitialiser le contenu et Paramètres...
    La prochaine fois que l'application sera exécutée, assurez-vous d'accepter l'invite des services de localisation.
  • Assurez-vous d'avoir un bon signal Wi-Fi ou GPS.
  • Si l'application se lance, mais qu'aucune carte ne s'affiche, vérifiez que vous avez mis à jour le fichier Info.plist de votre projet en indiquant l'emplacement approprié ; autorisations. Pour en savoir plus sur la gestion des autorisations, consultez le guide demander l'autorisation d'accéder à la position dans votre application. ci-dessous.
  • Utiliser les outils de débogage Xcode pour afficher les journaux et déboguer l'application.

Comprendre le code

Cette partie du tutoriel décrit les parties les plus importantes du current-place-on-map, pour vous aider à comprendre comment créer une application similaire.

L'application current-place-on-map dispose de deux contrôleurs de vue: Un pour afficher une carte montrant le lieu actuellement sélectionné par l'utilisateur, et un pour présenter à l'utilisateur une liste de lieux susceptibles de l'être. Notez que chaque contrôleur de vue possède les mêmes variables pour suivre la liste lieux probables (likelyPlaces) et pour indiquer l'adresse (selectedPlace). La navigation entre les vues en utilisant segues.

Demander l'autorisation d'accéder à la position

Votre application doit demander à l'utilisateur l'autorisation d'utiliser les services de localisation. À faire incluez la clé NSLocationAlwaysUsageDescription dans Info.plist de l'application et définissez la valeur de chaque clé sur un qui décrit comment l'application prévoit d'utiliser les données de localisation.

Configuration du gestionnaire d'établissements

Utilisez CLLocationManager pour déterminer la position actuelle de l'appareil et demander des mises à jour régulières lorsque le l'appareil change d'emplacement. Ce tutoriel fournit le code dont vous avez besoin pour la position de l'appareil. Pour en savoir plus, consultez le guide Obtenir la position de l'utilisateur dans la documentation pour les développeurs Apple.

  1. Déclarez le gestionnaire d'établissements, la position actuelle, la vue plan, le client Places, et le niveau de zoom par défaut au niveau de la classe.
  2. Swift

    var locationManager: CLLocationManager!
    var currentLocation: CLLocation?
    var mapView: GMSMapView!
    var placesClient: GMSPlacesClient!
    var preciseLocationZoomLevel: Float = 15.0
    var approximateLocationZoomLevel: Float = 10.0
          

    Objective-C

    CLLocationManager *locationManager;
    CLLocation * _Nullable currentLocation;
    GMSMapView *mapView;
    GMSPlacesClient *placesClient;
    float preciseLocationZoomLevel;
    float approximateLocationZoomLevel;
          
  3. Initialisez le gestionnaire d'établissements et GMSPlacesClient dans viewDidLoad()
  4. Swift

    // Initialize the location manager.
    locationManager = CLLocationManager()
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.requestWhenInUseAuthorization()
    locationManager.distanceFilter = 50
    locationManager.startUpdatingLocation()
    locationManager.delegate = self
    
    placesClient = GMSPlacesClient.shared()
          

    Objective-C

    // Initialize the location manager.
    locationManager = [[CLLocationManager alloc] init];
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    [locationManager requestWhenInUseAuthorization];
    locationManager.distanceFilter = 50;
    [locationManager startUpdatingLocation];
    locationManager.delegate = self;
    
    placesClient = [GMSPlacesClient sharedClient];
          
  5. Déclarez des variables pour contenir la liste des lieux probables et le lieu sélectionné par l'utilisateur.
  6. Swift

    // An array to hold the list of likely places.
    var likelyPlaces: [GMSPlace] = []
    
    // The currently selected place.
    var selectedPlace: GMSPlace?
          

    Objective-C

    // An array to hold the list of likely places.
    NSMutableArray<GMSPlace *> *likelyPlaces;
    
    // The currently selected place.
    GMSPlace * _Nullable selectedPlace;
          
  7. Ajoutez des délégués pour la gestion des événements pour le gestionnaire d'établissements, à l'aide d'une extension .
  8. Swift

    // Delegates to handle events for the location manager.
    extension MapViewController: CLLocationManagerDelegate {
    
      // Handle incoming location events.
      func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let location: CLLocation = locations.last!
        print("Location: \(location)")
    
        let zoomLevel = locationManager.accuracyAuthorization == .fullAccuracy ? preciseLocationZoomLevel : approximateLocationZoomLevel
        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) {
        // Check accuracy authorization
        let accuracy = manager.accuracyAuthorization
        switch accuracy {
        case .fullAccuracy:
            print("Location accuracy is precise.")
        case .reducedAccuracy:
            print("Location accuracy is not precise.")
        @unknown default:
          fatalError()
        }
    
        // Handle authorization status
        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.")
        @unknown default:
          fatalError()
        }
      }
    
      // Handle location manager errors.
      func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        locationManager.stopUpdatingLocation()
        print("Error: \(error)")
      }
    }
          

    Objective-C

    // Delegates to handle events for the location manager.
    #pragma mark - CLLocationManagerDelegate
    
    // Handle incoming location events.
    - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
    {
      CLLocation *location = locations.lastObject;
      NSLog(@"Location: %@", location);
    
      float zoomLevel = locationManager.accuracyAuthorization == CLAccuracyAuthorizationFullAccuracy ? preciseLocationZoomLevel : approximateLocationZoomLevel;
      GMSCameraPosition * camera = [GMSCameraPosition cameraWithLatitude:location.coordinate.latitude
                                                               longitude:location.coordinate.longitude
                                                                    zoom:zoomLevel];
    
      if (mapView.isHidden) {
        mapView.hidden = NO;
        mapView.camera = camera;
      } else {
        [mapView animateToCameraPosition:camera];
      }
    
      [self listLikelyPlaces];
    }
    
    // Handle authorization for the location manager.
    - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
    {
      // Check accuracy authorization
      CLAccuracyAuthorization accuracy = manager.accuracyAuthorization;
      switch (accuracy) {
        case CLAccuracyAuthorizationFullAccuracy:
          NSLog(@"Location accuracy is precise.");
          break;
        case CLAccuracyAuthorizationReducedAccuracy:
          NSLog(@"Location accuracy is not precise.");
          break;
      }
    
      // Handle authorization status
      switch (status) {
        case kCLAuthorizationStatusRestricted:
          NSLog(@"Location access was restricted.");
          break;
        case kCLAuthorizationStatusDenied:
          NSLog(@"User denied access to location.");
          // Display the map using the default location.
          mapView.hidden = NO;
        case kCLAuthorizationStatusNotDetermined:
          NSLog(@"Location status not determined.");
        case kCLAuthorizationStatusAuthorizedAlways:
        case kCLAuthorizationStatusAuthorizedWhenInUse:
          NSLog(@"Location status is OK.");
      }
    }
    
    // Handle location manager errors.
    - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
    {
      [manager stopUpdatingLocation];
      NSLog(@"Error: %@", error.localizedDescription);
    }
          

Ajouter une carte

Créez une carte et ajoutez-la à la vue de viewDidLoad() dans le et le contrôleur de vue principal. La carte reste masquée jusqu'à la réception d'une mise à jour de la position. (les mises à jour de la position sont gérées dans le CLLocationManagerDelegate ).

Swift

// A default location to use when location permission is not granted.
let defaultLocation = CLLocation(latitude: -33.869405, longitude: 151.199)

// Create a map.
let zoomLevel = locationManager.accuracyAuthorization == .fullAccuracy ? preciseLocationZoomLevel : approximateLocationZoomLevel
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
      

Objective-C

// A default location to use when location permission is not granted.
CLLocationCoordinate2D defaultLocation = CLLocationCoordinate2DMake(-33.869405, 151.199);

// Create a map.
float zoomLevel = locationManager.accuracyAuthorization == CLAccuracyAuthorizationFullAccuracy ? preciseLocationZoomLevel : approximateLocationZoomLevel;
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:defaultLocation.latitude
                                                        longitude:defaultLocation.longitude
                                                             zoom:zoomLevel];
mapView = [GMSMapView mapWithFrame:self.view.bounds camera:camera];
mapView.settings.myLocationButton = YES;
mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
mapView.myLocationEnabled = YES;

// Add the map to the view, hide it until we've got a location update.
[self.view addSubview:mapView];
mapView.hidden = YES;
      

Demander à l'utilisateur de sélectionner son lieu actuel

Utiliser le SDK Places pour iOS afin d'obtenir le top 5 des lieux de probabilité en fonction de la position actuelle de l'utilisateur, et de présenter la liste UITableView Lorsque l'utilisateur sélectionne un lieu, ajoutez un repère à la sur la carte.

  1. Obtenez une liste des lieux susceptibles d'occuper une UITableView. depuis laquelle l'utilisateur peut sélectionner l'endroit où il se trouve actuellement.
  2. Swift

    // Populate the array with the list of likely places.
    func listLikelyPlaces() {
      // Clean up from previous sessions.
      likelyPlaces.removeAll()
    
      let placeFields: GMSPlaceField = [.name, .coordinate]
      placesClient.findPlaceLikelihoodsFromCurrentLocation(withPlaceFields: placeFields) { (placeLikelihoods, error) in
        guard error == nil else {
          // TODO: Handle the error.
          print("Current Place error: \(error!.localizedDescription)")
          return
        }
    
        guard let placeLikelihoods = placeLikelihoods else {
          print("No places found.")
          return
        }
    
        // Get likely places and add to the list.
        for likelihood in placeLikelihoods {
          let place = likelihood.place
          self.likelyPlaces.append(place)
        }
      }
    }
          

    Objective-C

    // Populate the array with the list of likely places.
    - (void) listLikelyPlaces
    {
      // Clean up from previous sessions.
      likelyPlaces = [NSMutableArray array];
    
      GMSPlaceField placeFields = GMSPlaceFieldName | GMSPlaceFieldCoordinate;
      [placesClient findPlaceLikelihoodsFromCurrentLocationWithPlaceFields:placeFields callback:^(NSArray<GMSPlaceLikelihood *> * _Nullable likelihoods, NSError * _Nullable error) {
        if (error != nil) {
          // TODO: Handle the error.
          NSLog(@"Current Place error: %@", error.localizedDescription);
          return;
        }
    
        if (likelihoods == nil) {
          NSLog(@"No places found.");
          return;
        }
    
        for (GMSPlaceLikelihood *likelihood in likelihoods) {
          GMSPlace *place = likelihood.place;
          [likelyPlaces addObject:place];
        }
      }];
    }
          
  3. Ouvrez une nouvelle vue pour présenter les lieux probables à l'utilisateur. Lorsque l'utilisateur appuie sur "Get Place", nous accédons à une nouvelle vue et montrons à l'utilisateur une liste à choisir. La fonction prepare met à jour PlacesViewController par la liste des lieux probables actuels, et est appelé automatiquement lorsqu'une suite est effectuée.
  4. Swift

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

    Objective-C

    // Prepare the segue.
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
      if ([segue.identifier isEqualToString:@"segueToSelect"]) {
        if ([segue.destinationViewController isKindOfClass:[PlacesViewController class]]) {
          PlacesViewController *placesViewController = (PlacesViewController *)segue.destinationViewController;
          placesViewController.likelyPlaces = likelyPlaces;
        }
      }
    }
          
  5. Dans PlacesViewController, remplissez le tableau en utilisant la liste des les endroits probables, à l'aide de l'extension de délégation UITableViewDataSource.
  6. Swift

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

    Objective-C

    #pragma mark - UITableViewDataSource
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
      return self.likelyPlaces.count;
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
      return [tableView dequeueReusableCellWithIdentifier:cellReuseIdentifier forIndexPath:indexPath];
    }
    @end
          
  7. Gérer la sélection de l'utilisateur à l'aide de UITableViewDelegate déléguée.
  8. Swift

    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 a user selects a place.
    extension PlacesViewController: UITableViewDelegate {
      func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        selectedPlace = likelyPlaces[indexPath.row]
        performSegue(withIdentifier: "unwindToMain", sender: self)
      }
    
      // Adjust cell height to only show 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
      }
    }
          

    Objective-C

    @interface PlacesViewController () <UITableViewDataSource, UITableViewDelegate>
    // ...
    
    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
    
    }
    
    #pragma mark - UITableViewDelegate
    
    // Respond when a user selects a place.
    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
      self.selectedPlace = [self.likelyPlaces objectAtIndex:indexPath.row];
      [self performSegueWithIdentifier:@"unwindToMain" sender:self];
    }
    
    // Adjust cell height to only show the first five items in the table
    // (scrolling is disabled in IB).
    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
      return self.tableView.frame.size.height/5;
    }
    
    // Make table rows display at proper height if there are less than 5 items.
    -(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
    {
      if (section == tableView.numberOfSections - 1) {
        return 1;
      }
      return 0;
    }
          

Ajouter un repère à la carte

Lorsque l'utilisateur fait une sélection, utilisez une suite de détente pour revenir à la la vue précédente et ajouter le repère à la carte. unwindToMain IBAction est appelé automatiquement lorsque vous revenez au contrôleur de vue principal.

Swift

// 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 let place = selectedPlace {
    let marker = GMSMarker(position: place.coordinate)
    marker.title = selectedPlace?.name
    marker.snippet = selectedPlace?.formattedAddress
    marker.map = mapView
  }

  listLikelyPlaces()
}
      

Objective-C

// Update the map once the user has made their selection.
- (void) unwindToMain:(UIStoryboardSegue *)segue
{
  // Clear the map.
  [mapView clear];

  // Add a marker to the map.
  if (selectedPlace != nil) {
    GMSMarker *marker = [GMSMarker markerWithPosition:selectedPlace.coordinate];
    marker.title = selectedPlace.name;
    marker.snippet = selectedPlace.formattedAddress;
    marker.map = mapView;
  }

  [self listLikelyPlaces];
}
      

Félicitations ! Vous avez créé une application iOS qui permet à l'utilisateur de choisir leur position actuelle, et affiche le résultat sur une carte Google. Au cours de vous avez appris à utiliser SDK Places pour iOS le SDK Maps pour iOS, et le framework Apple Core Location.