Wybierz Bieżące miejsce i Pokaż szczegóły na mapie

W tym samouczku pokazujemy, jak utworzyć aplikację na iOS, która pobiera bieżącą lokalizację urządzenia, identyfikuje prawdopodobne lokalizacje, prosi użytkownika o wybranie najlepszego dopasowania i wyświetla znacznik mapy dla wybranej lokalizacji.

Jest on przeznaczony dla osób, które mają podstawową lub średnio zaawansowaną wiedzę o językach Swift lub Objective-C oraz ogólną wiedzę o Xcode. Zaawansowany przewodnik po tworzeniu map znajdziesz w przewodniku dla programistów.

W tym samouczku utworzysz mapę, która będzie wyglądać tak: Znacznik mapy jest umieszczony w San Francisco w stanie Kalifornia, ale będzie się przesuwać w zależności od lokalizacji urządzenia lub symulatora.

W tym samouczku używamy pakietu SDK Miejsc na iOS, pakietu SDK Map Google na iOS i platformy Apple Core Location.

Pobierz kod

Sklonuj lub pobierz repozytorium przykładów Google Maps iOS z GitHuba.

Możesz też kliknąć ten przycisk, aby pobrać kod źródłowy:

Podaj mi kod

MapViewController

Swift

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)")   } }       

Objective-C

#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       

PlacesViewController

Swift

import UIKit import GooglePlaces  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   } }  // 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

#import "PlacesViewController.h"  @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; }  #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       

Rozpocznij

Swift Package Manager

Pakiet Maps SDK na iOS można zainstalować za pomocą menedżera pakietów Swift.

  1. Usuń wszystkie istniejące zależności pakietu Maps SDK na iOS.
  2. Otwórz okno terminala i przejdź do katalogu tutorials/current-place-on-map.
  3. Zamknij obszar roboczy Xcode i uruchom te polecenia:
            sudo gem install cocoapods-deintegrate cocoapods-clean         pod deintegrate         pod cache clean --all         rm Podfile         rm current-place-on-map.xcworkspace
  4. Otwórz projekt Xcode i usuń plik podfile.
  5. Dodaj pakiety SDK Miejsc i Map:
    1. Kliknij Plik > Dodaj zależności pakietu.
    2. Wpisz https://github.com/googlemaps/ios-places-sdk, naciśnij Enter, aby pobrać pakiet, a potem kliknij Add Package (Dodaj pakiet).
    3. Wpisz https://github.com/googlemaps/ios-maps-sdk, naciśnij Enter, aby pobrać pakiet, a potem kliknij Add Package (Dodaj pakiet).
  6. Może być konieczne zresetowanie pamięci podręcznej pakietów. Aby to zrobić, wybierz Plik > Pakiety > Zresetuj pamięć podręczną pakietów.

Korzystanie z CocoaPods

  1. Pobierz i zainstaluj Xcodewersji 16.0 lub nowszej.
  2. Jeśli nie masz jeszcze CocoaPods, zainstaluj go w systemie macOS, uruchamiając w terminalu to polecenie:
    sudo gem install cocoapods
  3. Przejdź do katalogu tutorials/current-place-on-map.
  4. Uruchom polecenie pod install. Spowoduje to zainstalowanie pakietów SDK Map i Miejsc określonych w pliku Podfile wraz z wszelkimi zależnościami.
  5. Uruchom polecenie pod outdated, aby porównać zainstalowaną wersję poda z nowymi aktualizacjami. Jeśli wykryta zostanie nowa wersja, uruchom polecenie pod update, aby zaktualizować Podfile i zainstalować najnowszy pakiet SDK. Więcej informacji znajdziesz w przewodniku po CocoaPods.
  6. Otwórz (kliknij dwukrotnie) plik current-place-on-map.xcworkspace projektu, aby otworzyć go w Xcode. Aby otworzyć projekt, musisz użyć pliku .xcworkspace.

Uzyskiwanie klucza interfejsu API i włączanie niezbędnych interfejsów API

Aby wykonać zadania z tego samouczka, musisz mieć klucz interfejsu API Google, który ma autoryzację do korzystania z pakietu Maps SDK na iOSinterfejsu Places API.

  1. Aby skonfigurować konto rozliczeniowe i projekt z włączonymi usługami, postępuj zgodnie z instrukcjami w artykule Pierwsze kroki w Google Maps Platform.
  2. Aby utworzyć klucz interfejsu API dla skonfigurowanego wcześniej projektu deweloperskiego, postępuj zgodnie z instrukcjami w artykule Uzyskiwanie klucza interfejsu API.

Dodawanie klucza interfejsu API do aplikacji

Dodaj klucz interfejsu API do AppDelegate.swift w ten sposób:

  1. Zwróć uwagę, że do pliku dodano tę instrukcję importu:
    import GooglePlaces import GoogleMaps
  2. Edytuj w metodzie application(_:didFinishLaunchingWithOptions:) ten wiersz, zastępując YOUR_API_KEY kluczem interfejsu API:
    GMSPlacesClient.provideAPIKey("YOUR_API_KEY") GMSServices.provideAPIKey("YOUR_API_KEY")

Tworzenie i uruchamianie aplikacji

  1. Podłącz urządzenie z iOS do komputera lub wybierz symulator z menu schematu Xcode.
  2. Jeśli używasz urządzenia, upewnij się, że usługi lokalizacyjne są włączone. Jeśli używasz symulatora, wybierz lokalizację z menu Funkcje.
  3. W menu Xcode kliknij Product/Run (Usługa/Uruchom) lub ikonę przycisku odtwarzania.
  • Xcode skompiluje aplikację, a następnie uruchomi ją na urządzeniu lub w symulatorze.
  • Powinna się wyświetlić mapa z kilkoma znacznikami wyśrodkowanymi wokół Twojej bieżącej lokalizacji.

Rozwiązywanie problemów:

  • Jeśli nie widzisz mapy, sprawdź, czy masz klucz interfejsu API i czy został on dodany do aplikacji w sposób opisany powyżej. Sprawdź w konsoli debugowania Xcode komunikaty o błędach dotyczące klucza interfejsu API.
  • Jeśli klucz interfejsu API jest ograniczony przez identyfikator pakietu iOS, edytuj klucz, aby dodać identyfikator pakietu aplikacji:com.google.examples.current-place-on-map.
  • Jeśli odrzucisz prośbę o zezwolenie na usługi lokalizacyjne, mapa nie będzie się wyświetlać prawidłowo.
    • Jeśli używasz urządzenia, otwórz Ustawienia/Ogólne/Prywatność/Usługi lokalizacyjne i ponownie włącz usługi lokalizacyjne.
    • Jeśli używasz symulatora, kliknij Symulator/Resetuj zawartość i ustawienia…
    Przy następnym uruchomieniu aplikacji zaakceptuj prośbę o dostęp do usług lokalizacyjnych.
  • Upewnij się, że masz dobre połączenie Wi-Fi lub GPS.
  • Jeśli aplikacja uruchamia się, ale nie wyświetla mapy, sprawdź, czy plik Info.plist w projekcie został zaktualizowany o odpowiednie uprawnienia do lokalizacji. Więcej informacji o obsłudze uprawnień znajdziesz w przewodniku przesyłania próśb o uprawnienia do lokalizacji w aplikacji poniżej.
  • Użyj narzędzi do debugowania Xcode, aby wyświetlić dzienniki i debugować aplikację.

Zrozumienie kodu

W tej części samouczka wyjaśniamy najważniejsze elementy aplikacji current-place-on-map, aby pomóc Ci w utworzeniu podobnej aplikacji.

Aplikacja current-place-on-map zawiera 2 kontrolery widoku: jeden do wyświetlania mapy z wybranym przez użytkownika miejscem, a drugi do prezentowania użytkownikowi listy prawdopodobnych miejsc do wyboru. Zwróć uwagę, że każdy kontroler widoku ma te same zmienne do śledzenia listy prawdopodobnych miejsc (likelyPlaces) i wskazywania wyboru użytkownika (selectedPlace). Nawigacja między widokami odbywa się za pomocą przejść.

Wysyłanie prośby o dostęp do lokalizacji

Aplikacja musi poprosić użytkownika o zgodę na korzystanie z usług lokalizacji. Aby to zrobić, w pliku Info.plist aplikacji umieść klucz NSLocationAlwaysUsageDescription i ustaw wartość każdego klucza na ciąg znaków opisujący, w jaki sposób aplikacja zamierza używać danych o lokalizacji.

Konfigurowanie menedżera lokalizacji

Użyj CLLocationManager, aby znaleźć bieżącą lokalizację urządzenia i regularnie otrzymywać aktualizacje, gdy urządzenie przeniesie się w nowe miejsce. W tym samouczku znajdziesz kod potrzebny do uzyskania lokalizacji urządzenia. Więcej informacji znajdziesz w przewodniku Getting the User's Location w dokumentacji dla programistów Apple.

  1. Zadeklaruj menedżera lokalizacji, bieżącą lokalizację, widok mapy, klienta miejsc i domyślny poziom powiększenia na poziomie klasy.
  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. Zainicjuj menedżera lokalizacji i GMSPlacesClientviewDidLoad().
  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. Zadeklaruj zmienne, które będą przechowywać listę prawdopodobnych miejsc i wybrane przez użytkownika miejsce.
  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. Dodaj osoby upoważnione do obsługi zdarzeń w imieniu menedżera lokalizacji, używając klauzuli rozszerzenia.
  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); }       

Dodawanie mapy

Utworzenie mapy i dodanie jej do widoku w viewDidLoad() w głównym kontrolerze widoku. Mapa pozostaje ukryta do momentu otrzymania aktualizacji lokalizacji (aktualizacje lokalizacji są obsługiwane w rozszerzeniu 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;       

Prośba o wybranie bieżącego miejsca

Użyj pakietu SDK Miejsc na iOS, aby uzyskać 5 najbardziej prawdopodobnych miejsc na podstawie bieżącej lokalizacji użytkownika i wyświetlić listę w UITableView. Gdy użytkownik wybierze miejsce, dodaj do mapy znacznik.

  1. Pobierz listę prawdopodobnych miejsc, aby wypełnić UITableView, z której użytkownik może wybrać miejsce, w którym się znajduje.
  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. Otwórz nowy widok, aby przedstawić użytkownikowi prawdopodobne miejsca. Gdy użytkownik kliknie „Pobierz miejsce”, przejdziemy do nowego widoku i wyświetlimy listę możliwych miejsc do wyboru. Funkcja preparePlacesViewController aktualizuje listę bieżących prawdopodobnych miejsc i jest wywoływana automatycznie po wykonaniu przejścia.
  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. PlacesViewController wypełnij tabelę, korzystając z listy najbardziej prawdopodobnych miejsc, używając rozszerzenia 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. Obsłuż wybór użytkownika za pomocą UITableViewDelegate rozszerzenia delegata.
  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; }       

Dodawanie znacznika do mapy

Gdy użytkownik dokona wyboru, użyj przejścia unwind, aby wrócić do poprzedniego widoku i dodać znacznik do mapy. Funkcja unwindToMain IBAction jest wywoływana automatycznie po powrocie do głównego kontrolera widoku.

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

Gratulacje! Masz aplikację na iOS, która umożliwia użytkownikowi wybranie bieżącego miejsca i wyświetlenie wyniku na mapie Google. W trakcie tego procesu dowiesz się, jak korzystać z pakietu SDK Miejsc na iOS, pakietu Maps SDK na iOSplatformy Apple Core Location.