Primeros pasos con el SDK de Places para iOS (Objective-C)

1. Antes de comenzar

Antes de comenzar a programar, debes configurar algunos requisitos previos.

Xcode

En este instructivo, se usa la herramienta Xcode de Apple y el lenguaje Objective-C para crear una app de iOS simple que se ejecute en un emulador. No necesitas un dispositivo físico. Puedes obtener Xcode en https://developer.apple.com/xcode/

CocoaPods

El SDK de Places para iOS está disponible como un pod de CocoaPods. CocoaPods es una herramienta de administración de dependencias de código abierto para proyectos de Swift y Objective-C. Si aún no la tienes, deberás instalarla antes de continuar. Se puede instalar desde la terminal de la siguiente manera:

sudo gem install cocoapods

Para obtener más detalles sobre CocoaPods, consulta la guía de introducción de CocoaPods.

Instalar el SDK

Para instalar el SDK, debes crear un Podfile en el directorio de tu proyecto que CocoaPods usará para descargar y configurar las dependencias necesarias. La manera más sencilla de hacerlo es crear un proyecto nuevo en Xcode, agregar allí un Podfile.

Abre Xcode. Verás la pantalla "Welcome to Xcode #39". Aquí, selecciona "Crear un nuevo proyecto de Xcode" (Create a new Xcode project).

4f1ecee473937c7b.png

En la siguiente pantalla, se te pedirá una plantilla para tu proyecto nuevo. Selecciona “Single View Application” para iOS y presiona “Next” (Siguiente).

Cuando se te solicite el nombre del producto, puedes elegir lo que quieras, pero asegúrate de tener en cuenta el identificador de paquete que se genera para ti. La necesitarás más tarde.

72fbf25cb2db22ad.png

Presiona "Siguiente"; se creará el proyecto. Toma nota del directorio en el que se crea. Cierra Xcode y usa Terminal para ir a ese directorio.

Ingresa el siguiente comando en la terminal:

pod init

Se creará un archivo llamado Podfile. Edítalo para que agregue un Pod para GoogleMaps de la siguiente manera:

target '{YOUR APP NAME}' do
pod 'GoogleMaps'
end

Guárdala y cierra Xcode. Asegúrate de cerrarlo, ya que, en el siguiente paso, editarás el proyecto subyacente. Abrirás un archivo de proyecto diferente cuando esté listo, y es bastante común que un desarrollador se confunda con respecto a dónde se encuentra todo si no cerró Xcode anteriormente. En una terminal, ve al directorio del proyecto y ejecuta "pod install" como se muestra a continuación:

789c5bc62817f68a.png

Una vez que hayas terminado, se instalarán los pods y se creará un nuevo archivo .xcworkspace. Úsalo para el proyecto a partir de ahora. Pero antes de programar, lo siguiente que necesitarás es una clave de API.

2. Obtén tu clave de API

Para el siguiente paso, debes habilitar el SDK de Maps para iOS.

Configura Google Maps Platform

Si todavía no tienes una cuenta de Google Cloud Platform y un proyecto con la facturación habilitada, consulta la guía Cómo comenzar a utilizar Google Maps Platform para crear una cuenta de facturación y un proyecto.

  1. En Cloud Console, haz clic en el menú desplegable del proyecto y selecciona el proyecto que deseas usar para este codelab.

  1. Habilita las API y los SDK de Google Maps Platform necesarios para este codelab en Google Cloud Marketplace. Para hacerlo, sigue los pasos que se indican en este video o esta documentación.
  2. Genera una clave de API en la página Credenciales de Cloud Console. Puedes seguir los pasos que se indican en este video o esta documentación. Todas las solicitudes a Google Maps Platform requieren una clave de API.

3. Cómo crear la app de la API de Places

Ahora que creaste un proyecto de la consola y activaste la API de Places en ella, y que obtuviste una clave de API, estás listo para comenzar a programar tu primera app de la API de Places.

Anteriormente, cuando instaló los archivos del Pod, se creó un archivo .xcworkspace nuevo para usted. Para abrir esta opción, haga doble clic en ella.

19d62f34c08e645c.png

En el Explorador de proyectos, verá que tiene una nueva carpeta llamada “Pods”. Si funcionó correctamente, verás una carpeta de Google Maps allí con los frameworks.

8844d861f64c61aa.png

4. Edita el archivo Info.plist.

Cuando ejecutes la aplicación por primera vez, iOS te mostrará un diálogo que le pedirá al usuario que otorgue permiso para acceder a los servicios de ubicación. Este diálogo mostrará una string que usted definirá y la colocará en el archivo Info.plist. Si no aparece esta string, no se mostrará el diálogo y la app no funcionará.

Puedes encontrar el archivo Info.plist en el explorador del proyecto aquí:

c224c920ab3f1ef.png

Selecciónalo y verás el editor de plist.

859ca56f3b19da5.png

Coloca el cursor sobre cualquiera de los elementos para que aparezca el ícono “+”. Presiónalo para ver una nueva entrada. Ingresa el valor "NSLocationAlwaysUsageDescription' en este cuadro.

9fb225d6f5508794.png

Presiona Intro para agregar la llave nueva. Luego, haga doble clic en la columna Valor de esta clave y agregue una string:

5aefeb184187aa58.png

Si deseas obtener más información sobre esta string, consulta la documentación para desarrolladores de Apple aquí.

5. Editar el delegado de la app

En el explorador del proyecto, busca y abre AppDelegate.m. Lo usarás para agregar tu clave de API.

En la parte superior del archivo, agregue esta información inmediatamente debajo de la línea #import:

@import GoogleMaps;

Luego, en la función didFinishLaunchingWithOptions:, agrega lo siguiente sobre la línea "return YES'":

[GMSServices provideAPIKey:@"<Add your API Key>"];

Asegúrate de usar la clave de API que generaste antes.

6. Edita el archivo de guion

En el explorador del proyecto, abre el archivo Main.storyboard. Asegúrate de que la barra lateral esté activa presionando el botón de la barra lateral en la esquina superior derecha.

352af28b970d9e2.png

Luego, en la parte inferior de la barra lateral, busca el control de etiquetas y asegúrate de que esté seleccionada la biblioteca de objetos.

adec7051ae949531.png

En la vista de controladores de vista del lado izquierdo, asegúrate de que esté seleccionada la opción "Ver:":

e4827b92b5861e3e.png

Luego, arrastra y suelta las 7 etiquetas en la vista. Ordénalos como se muestra aquí. Asegúrate de arrastrar sus tamaños para que coincidan con lo que se muestra. Para editar el texto de la etiqueta, haga doble clic en él y escriba el valor requerido:

f8a9457772358069.png

En la etiqueta de la parte inferior (la más grande), ve al editor de propiedades y asegúrate de que esté configurado en 0 líneas (el valor predeterminado es 1). De esa manera, se podrán renderizar varias líneas.

a4abacf00d8888fe.png

7. Crea salidas para los valores

Debes crear un tomacorriente para las 3 etiquetas "value" [valor]. De esa manera, podrás cambiar sus valores mediante código. Para ello, primero debes activar el editor del Asistente. Para ello, primero debes cerrar la barra lateral de propiedades. Para ello, haz clic en su botón a fin de quitarla. (Este botón se mostró en el paso anterior)

Luego, selecciona el botón del Asistente, que es el círculo doble que se muestra aquí:

e92dcc4ceea20a51.png

Asegúrate de que renderice el archivo ViewController.h. Si no lo es, puedes cambiarla desde el editor que se encuentra en la parte superior de la ventana del asistente.

d42f0fcc18b84703.png

Luego, cuando mantengas presionada la tecla CONTROL, arrastra cada etiqueta y suéltala debajo de la línea @interface en el archivo ViewController.h del asistente. Aparecerá un diálogo que te preguntará qué tipo de conexión quieres establecer:

a44b7888ed0f62b.png

Asegúrate de que la configuración sea como se muestra (Conexión: Outlet; Tipo: UILabel; Almacenamiento: Débil). Luego, asígnale un nombre. Para los fines de este codelab, llamé las etiquetas de longitud, latitud y altitud lblLongitude, lbllatitude y lblAltidude, respectivamente. También arrastre la etiqueta grande desde la parte inferior hacia arriba y llámela lblPlaces.

Cuando termines, tu archivo ViewController.h debería verse de esta forma:

#import <UIKit/UIKit.h>
@import GoogleMaps;

@interface ViewController : UIViewController
@property (weak, nonatomic) IBOutlet UILabel *lblLatitude;
@property (weak, nonatomic) IBOutlet UILabel *lblLongitude;
@property (weak, nonatomic) IBOutlet UILabel *lblAltitude;
@property (weak, nonatomic) IBOutlet UILabel *lblPlaces;

@end

8. Edita el archivo de encabezado para las API de ubicación y de cliente de Google

Antes de los pasos finales (en los que compilarás la app para usar la API de Places), debes configurar algunas variables más en el archivo de encabezado (ViewController.h). Estos son el Core Location Manager y un objeto Core Location:

@property (strong, nonatomic) CLLocationManager *locationManager;
@property (strong, nonatomic) CLLocation *location;

También necesitarás un cliente de la API de Google:

@property GMSPlacesClient *placesClient;

Por último, deberás actualizar el archivo de encabezado para que la clase implemente CLLocationManagerDelegate:

@interface ViewController : UIViewController<CLLocationManagerDelegate>

Cuando termines, el archivo de encabezado debería verse de la siguiente manera:

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <GoogleMaps/GoogleMaps.h>


@interface ViewController : UIViewController<CLLocationManagerDelegate>
@property (strong, nonatomic) CLLocationManager *locationManager;
@property (strong, nonatomic) CLLocation *location;
@property (weak, nonatomic) IBOutlet UILabel *lblLongitude;
@property (weak, nonatomic) IBOutlet UILabel *lblLatitude;
@property (weak, nonatomic) IBOutlet UILabel *lblAltitude;
@property (weak, nonatomic) IBOutlet UILabel *lblPlaces;

@property GMSPlacesClient *placesClient;
@end

9. Edita tu controlador de vista

El primer paso es editar la función viewdidLoad para inicializar el administrador de ubicaciones, solicitar la autorización del usuario a fin de acceder a la ubicación y, finalmente, iniciar el administrador de ubicaciones para que realice un seguimiento de la ubicación actual. También inicializarás el cliente de la API de Google Places.

- (void)viewDidLoad {
    [super viewDidLoad];
    self.locationManager = [[CLLocationManager alloc]init];
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
        [self.locationManager requestAlwaysAuthorization];
        // Or [self.locationManager requestWhenInUseAuthorization];
    }
    [self.locationManager startUpdatingLocation];
    
    self.locationManager.delegate = self;
    self.location = [[CLLocation alloc] init];
    self.placesClient = [GMSPlacesClient sharedClient];
}

10. Cómo controlar las actualizaciones de ubicación

El administrador de ubicación volverá a llamar a tu controlador de vista con las actualizaciones de ubicación mediante una llamada a la función didUpdateLocations. Deberás agregarlo a tu ViewController.m. La función se ve así:

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
    // Enter code here
}

Esta función deberá completar varias tareas.

Primero, almacenará en caché la ubicación que recibió la última ubicación:

self.location = locations.lastObject;

Luego, se deben actualizar las tres etiquetas para Latitud, Longitud y Altitud:

self.lblLatitude.text = [NSString stringWithFormat:@"%f", self.location.coordinate.latitude];

self.lblLongitude.text = [NSString stringWithFormat:@"%f", self.location.coordinate.longitude];

self.lblAltitude.text = [NSString stringWithFormat:@"%f", self.location.altitude];

A continuación, llamará a la API de Places con el cliente de Places. Para ello, especifica la función de devolución de llamada, que obtendrá la lista de probabilidades de lugar. La API de Places determina la probabilidad de que estés en un lugar en particular según tu ubicación. Muestra el nombre de los posibles lugares, junto con un valor entre 0 y 1 que contiene la probabilidad de que te encuentres en ese lugar.

[self.placesClient currentPlaceWithCallback:^(GMSPlaceLikelihoodList *likelihoodList, NSError *error) {

Luego, puedes implementar la devolución de llamada. Esto te permitirá iterar en la lista de probabilidades, agregar lugares y probabilidades para esos lugares.

[self.placesClient currentPlaceWithCallback:^(GMSPlaceLikelihoodList *likelihoodList, NSError *error) {

  if (error != nil) {
    NSLog(@"Current Place error %@", [error localizedDescription]);
    return;
  }
  NSMutableString *strPlaces = [NSMutableString stringWithString:@""];

  for (GMSPlaceLikelihood *likelihood in likelihoodList.likelihoods) {
    GMSPlace* place = likelihood.place;
    NSLog(@"Current Place name %@ at likelihood %g", place.name,
            likelihood.likelihood);
    NSLog(@"Current Place address %@", place.formattedAddress);
    NSLog(@"Current Place attributions %@", place.attributions);
    NSLog(@"Current PlaceID %@", place.placeID);
    [strPlaces appendString:place.name];
    [strPlaces appendString:@" "];
    [strPlaces appendFormat:@"%g",likelihood.likelihood];
    [strPlaces appendString:@"\n"];
  }
  self.lblPlaces.text = strPlaces;
}];

Cuando termines, tu función didUpdateLocations se verá de la siguiente manera:

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations{
    
    self.location = locations.lastObject;
    self.lblLatitude.text = [NSString stringWithFormat:@"%f", self.location.coordinate.latitude];
    self.lblLongitude.text = [NSString stringWithFormat:@"%f", self.location.coordinate.longitude];
    self.lblAltitude.text = [NSString stringWithFormat:@"%f", self.location.altitude];
    
    NSLog(@"%@", self.location.description);
    
    [self.placesClient currentPlaceWithCallback:^(GMSPlaceLikelihoodList *likelihoodList, NSError *error) {

        if (error != nil) {
            NSLog(@"Current Place error %@", [error localizedDescription]);
            return;
        }
        NSMutableString *strPlaces = [NSMutableString stringWithString:@""];
        
        for (GMSPlaceLikelihood *likelihood in likelihoodList.likelihoods)  
        {
            GMSPlace* place = likelihood.place;
            NSLog(@"Current Place name %@ at likelihood %g", place.name, likelihood.likelihood);
            NSLog(@"Current Place address %@", place.formattedAddress);
            NSLog(@"Current Place attributions %@", place.attributions);
            NSLog(@"Current PlaceID %@", place.placeID);
            [strPlaces appendString:place.name];
            [strPlaces appendString:@" "];
            [strPlaces appendFormat:@"%g",likelihood.likelihood];
            [strPlaces appendString:@"\n"];
        }
        self.lblPlaces.text = strPlaces;
    }];
}

Ya puedes ejecutar tu app y probarla.

11. Cómo ejecutar la app en el emulador

Puedes ejecutar la app con el botón de ejecución de la barra de título. Esto también te permite seleccionar el tipo de ejecución y, como puedes ver aquí, realizar pruebas en un iPhone 6 usando el emulador.

bbbe0b8820c8a913.png

Cuando presiones el botón Ejecutar, se compilará y se iniciará la app. Verás una solicitud para permitir que la app acceda a la ubicación, incluida la string personalizada que especificaste anteriormente.

b9bb2ace7e68f186.png

Una vez que lo hagas, verás tus actualizaciones de latitud y longitud. Para cambiar la ubicación, selecciona el menú Depuración y elige una ubicación. Por ejemplo, puedes elegir "Viaje en autopista"

dcb1ce091d780f56.png

Cuando lo hagas, verás la ubicación actual con los posibles lugares en los que se estaban simulando los viajes en auto.

649e3eeb2321ae03.png

Eso es todo. Accediste correctamente a los detalles actuales del lugar con la API de Google Places en iOS.