Places SDK for iOS (Objective-C) 使用入门

1. 准备工作

在开始编写代码之前,您需要设置一些前提条件。

Xcode

本教程使用 Apple 的 Xcode 工具以及 Objective-C 语言来创建一个在模拟器中运行的简单 iOS 应用。您无需使用实体设备。您可以访问 https://developer.apple.com/xcode/ 获取 Xcode

CocoaPods

Places SDK for iOS 以 CocoaPods pod 的形式提供。CocoaPods 是一种用于 Swift 和 Objective-C 项目的开源依赖项管理工具。如果您还没有此工具,则需要先安装它,然后才能继续操作。您可以从终端安装它,如下所示:

sudo gem install cocoapods

如需详细了解 CocoaPods,请参阅 CocoaPods 入门指南

安装 SDK

如需安装 SDK,您需要在项目目录中创建一个 Podfile,CocoaPods 将使用该文件下载并配置所需的依赖项。最简单的方法是在 Xcode 中创建一个新项目,向其中添加 Podfile,然后在其中安装 pod。

打开 Xcode,您会看到“欢迎使用 Xcode”界面。在此处,选择“Create a new Xcode project”(新建 Xcode 项目)

4f1ecee473937c7b.png

在下一个界面中,系统会要求您为新项目选择模板。为 iOS 选择“Single View Application”,然后按“Next”

当系统要求您提供商品名称时,您可以选择任何喜欢的名称,但请务必记下为您生成的软件包标识符。您稍后会用到此内容。

72fbf25cb2db22ad.png

按“下一步”,系统将为您创建项目。记下创建该文件的目录。关闭 Xcode,然后使用终端导航到该目录。

使用终端,输入以下命令:

pod init

系统将为您创建一个名为 Podfile 的文件。修改该文件,添加 GoogleMaps 的 pod,如下所示:

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

保存该文件,然后关闭 Xcode。请务必关闭该项目,因为在下一步中,您将修改底层项目。完成后,您将打开另一个项目文件,如果开发者之前未关闭 Xcode,很容易混淆所有内容的位置!现在,在终端中,前往您的项目目录,然后运行“pod install”,如下所示:

789c5bc62817f68a.png

完成后,系统会安装 pod 并创建一个新的 .xcworkspace 文件。从现在开始,请在项目中改用此账号。不过,在编码之前,您还需要一个 API 密钥。

2. 获取 API 密钥

为了完成以下启用步骤,请启用 Maps SDK for iOS

设置 Google Maps Platform

如果您还没有已启用结算功能的 Google Cloud Platform 账号和项目,请参阅 Google Maps Platform 使用入门指南,创建结算账号和项目。

  1. Cloud Console 中,点击项目下拉菜单,选择要用于此 Codelab 的项目。

  1. Google Cloud Marketplace 中启用此 Codelab 所需的 Google Maps Platform API 和 SDK。为此,请按照此视频此文档中的步骤操作。
  2. 在 Cloud Console 的凭据页面中生成 API 密钥。您可以按照此视频此文档中的步骤操作。向 Google Maps Platform 发出的所有请求都需要 API 密钥。

3. 创建 Places API 应用

现在,您已创建控制台项目,并在其中激活 Places API,还获取了 API 密钥,接下来就可以开始编写您的第一个 Places API 应用了。

之前在安装 pod 文件时,系统为您创建了一个新的 .xcworkspace 文件。双击此文件将其打开。

19d62f34c08e645c.png

您会在项目资源管理器中看到,现在多了一个名为“Pods”的新文件夹。如果此操作成功,您会在其中看到一个包含框架的 GoogleMaps 文件夹。

8844d861f64c61aa.png

4. 修改 Info.plist 文件。

首次运行应用时,iOS 会显示一个对话框,要求用户授予访问位置信息服务的权限。此对话框将提供您定义的字符串,您只需将其放入 Info.plist 文件中即可。如果不存在此字符串,则不会显示对话框,并且应用将无法正常运行。

您可以在项目资源管理器中找到 Info.plist 文件,如下所示:

c224c920ab3f1ef.png

选择该文件,您会看到 plist 编辑器。

859ca56f3b19da5.png

将鼠标悬停在任意元素上,您会看到“+”图标。按一下,您会看到出现一个新条目。在此框中输入值“NSLocationAlwaysUsageDescription”。

9fb225d6f5508794.png

按 Enter 键即可添加新密钥。然后,双击相应键的“值”列,并添加一个字符串:

5aefeb184187aa58.png

如需详细了解此字符串,请参阅 Apple 开发者文档(点击此处)。

5. 修改应用委托

在项目浏览器中,找到并打开 AppDelegate.m。您将使用此文件添加 API 密钥。

在文件顶部,在 #import 行下方立即添加以下内容:

@import GoogleMaps;

然后,在 didFinishLaunchingWithOptions: 函数中,在“return YES”行上方添加以下代码:

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

请务必使用您之前生成的 API 密钥。

6. 修改故事板文件

在项目浏览器中,打开 Main.storyboard 文件。按右上角的边栏按钮,确保边栏处于活动状态。

352af28b970d9e2.png

然后,在边栏底部,确保已选择“对象库”,找到“标签控件”。

adec7051ae949531.png

在左侧的视图控制器场景中,确保已选择“视图”:

e4827b92b5861e3e.png

然后,将 7 个标签拖放到视图中。按此处所示的顺序排列。请务必拖动其大小,使其与显示的尺寸一致。您可以双击标签中的文字,然后输入所需的值,以修改标签中的文字:

f8a9457772358069.png

对于最底部的标签(非常大的标签),请前往属性编辑器,并确保将其设置为 0 行(默认值为 1)。这样,标签就可以呈现多行。

a4abacf00d8888fe.png

7. 为值创建 Outlet

对于这 3 个“值”标签,您需要创建一个插座。这样,您就可以使用代码更改这些变量的值。为此,您需要先激活助理编辑器。为此,请先点击属性边栏的按钮将其移除,以关闭该边栏。(此按钮在上一步中显示过)

然后,选择 Google 助理按钮(即此处显示的双圆圈按钮):

e92dcc4ceea20a51.png

确保它正在渲染 ViewController.h 文件。如果不是,您可以使用助理窗口顶部的编辑器将其更改为是:

d42f0fcc18b84703.png

然后,按住 CONTROL 键,将每个标签拖放到助理中的 ViewController.h 文件内的 @interface 行下方。系统会弹出一个对话框,询问您要建立哪种类型的连接:

a44b7888ed0f62b.png

确保设置如图所示(连接:Outlet;类型:UILabel;存储:Weak),然后为每个设置命名。在此 Codelab 中,我将经度、纬度和海拔标签分别命名为 lblLongitude、lblLatitude 和 lblAltidude。另外,从底部拖动大标签,并将其命名为 lblPlaces。

完成后,您的 ViewController.h 文件应如下所示:

#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. 修改位置信息和 Google 客户端 API 的头文件

在最后一步(构建应用以使用 Places API)之前,您需要在头文件 (ViewController.h) 中设置一些其他变量。以下是核心位置信息管理器和核心位置信息对象:

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

您还需要一个 Google API 客户端:

@property GMSPlacesClient *placesClient;

最后,您需要更新头文件,以便该类实现 CLLocationManagerDelegate:

@interface ViewController : UIViewController<CLLocationManagerDelegate>

完成后,您的头文件应如下所示:

#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. 修改视图控制器

第一步是修改 viewDidLoad 函数,以初始化位置管理器、请求用户授权访问位置信息,并最终启动位置管理器,以便其跟踪当前位置。您还将初始化 Google Places API 客户端。

- (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. 处理位置信息更新

位置信息管理器将通过调用 didUpdateLocations 函数来回调您的视图控制器,并提供位置信息更新。您需要将此函数添加到 ViewController.m 中。该函数如下所示:

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

此函数需要执行多项操作。

首先,它会缓存上次收到的位置信息:

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

接下来,您将使用 Places 客户端调用 Places API。为此,您可以指定回调函数,该函数将获取地点似然性列表。Places API 会根据您的位置信息确定您身处特定地点的可能性。它会返回可能的地点的名称,以及一个介于 0 到 1 之间的值,其中包含您在该地点的概率。

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

然后,您可以实现回调。此代码将遍历可能性列表,并添加地点和这些地点的可能性。

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

完成后,您的 didUpdateLocations 函数应如下所示:

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

您现在可以运行应用并进行测试了!

11. 在模拟器中运行应用

您可以使用标题栏中的“运行”按钮运行应用。您还可以选择运行类型,如您在此处看到的,我正在使用模拟器在 iPhone 6 上进行测试。

bbbe0b8820c8a913.png

当您按下运行按钮时,应用将构建并启动。您会看到允许应用访问位置信息的请求,其中包含您之前指定的自定义字符串。

b9bb2ace7e68f186.png

完成此操作后,您会看到纬度和经度更新。如需更改位置,请选择“调试”菜单,然后选择一个位置。例如,您可以选择“高速公路驾驶”

dcb1ce091d780f56.png

执行此操作后,您会看到位置信息及其可能的位置在更新,模拟高速公路驾驶。

649e3eeb2321ae03.png

这样就大功告成了!您已成功在 iOS 上使用 Google Places API 访问当前地点的详细信息。