设置 Xcode 项目

启用结算功能并创建 API 密钥后,您就可以设置用于开发应用的 Xcode 项目。

每个版本都有相应的版本说明

第 1 步:安装所需的软件

如需使用 Places SDK for iOS 构建项目,您需要:

  • Xcode 版本 15.0 或更高版本

第 2 步:创建 Xcode 项目并安装 Places SDK for iOS

Swift Package Manager

Places SDK for iOS 可通过 Swift Package Manager 安装。如需添加该 SDK,请确保您已移除所有现有的 Places SDK for iOS 依赖项。

要将 SDK 添加到新项目或现有项目,请按以下步骤操作:

  1. 打开 Xcode projectworkspace,然后前往 File(文件)> Add Package Dependencies(添加软件包依赖项)
  2. 输入 https://github.com/googlemaps/ios-places-sdk 作为网址,按 Enter 键拉取软件包,然后点击“Add Package”(添加软件包)。
  3. 如需安装特定的 version,请将依赖项规则字段设置为某个基于版本的选项。对于新项目,我们建议指定最新版本并使用“确切版本”选项。完成后,点击“添加文件包”。
  4. Choose Package Products 窗口中,确认 GooglePlaces 会添加到指定的 main 目标。完成后,点击“添加软件包”。
  5. 如需验证安装,请前往目标的 General 窗格。在框架、库和嵌入式内容中,您应该会看到已安装的软件包。 您还可以查看“项目导航器”的“软件包依赖项”部分,以验证软件包及其版本。

如需更新现有项目的 package,请按以下步骤操作:

  1. 如果要从 9.0.0 之前的版本升级,则必须在升级后移除以下依赖项:GoogleMapsBaseGoogleMapsCoreGoogleMapsM4B。请勿移除对 GoogleMaps 的依赖项。如需了解详情,请参阅 9.0.0 版版本说明

    在 Xcode 项目配置设置中,找到 Frameworks、Libraries, and Embedded Content。使用减号(-) 移除以下框架:

    • GoogleMapsBase(仅适用于从 9.0.0 之前的版本升级而来)
    • GoogleMapsCore(仅适用于从 9.0.0 之前的版本升级而来)
    • GoogleMapsM4B(仅适用于从 9.0.0 之前的版本升级而来)
  2. 在 Xcode 中,转到“File(文件)> Packages”(软件包)>“Update To Latest Package Versions”(更新软件包版本)”。
  3. 如需验证安装,请前往项目导航器软件包依赖项部分,验证软件包及其版本。

如需移除使用 CocoaPods 添加的现有 Places SDK for iOS 依赖项,请按以下步骤操作:

  1. 关闭 Xcode 工作区。打开终端并执行以下命令:
    sudo gem install cocoapods-deintegrate cocoapods-clean 
    pod deintegrate 
    pod cache clean --all
  2. 如果您不将 PodfilePodfile.resolved 和 Xcode workspace 用于 CocoaPods 以外的其他用途,请移除它们。

如需移除手动安装的现有 Places SDK for iOS,请按以下步骤操作:
  1. 在 Xcode 项目配置设置中,找到 Frameworks、Libraries, and Embedded Content。使用减号(-) 移除以下框架:
    • GooglePlaces.xcframework
  2. 从 Xcode 项目的顶级目录中,移除 GooglePlaces 软件包。

CocoaPods

Places SDK for iOS 以 CocoaPod pod(即 GooglePlaces)的形式提供,其中包含所有地点功能。

CocoaPods 是一种用于 Swift 和 Objective-C Cocoa 项目的开源依赖项管理器。如果您尚未安装 CocoaPods 工具,请在 macOS 上从终端运行以下命令进行安装。如需了解详情,请参阅 CocoaPods 入门指南

sudo gem install cocoapods

为 Places SDK for iOS 创建 Podfile,并使用它来安装 SDK 及其依赖项:

  1. 如果您尚未创建 Xcode 项目,请立即创建一个并将其保存到您的本地计算机上。如果您刚开始接触 iOS 开发,请创建一个新项目,然后选择 iOS App template
  2. 在您的项目目录中创建一个名为 Podfile 的文件。此文件可定义您项目的依赖项。
  3. 修改 Podfile,然后添加您的依赖项及其versions。以下示例指定了应用目标名称和 GooglePlaces pod 的名称:
    source 'https://github.com/CocoaPods/Specs.git'
    
    platform :ios, '15.0'
    
    target 'YOUR_APPLICATION_TARGET_NAME_HERE' do
      pod 'GooglePlaces', '8.3.0'
    end
    
    请务必定期运行 pod outdated 以检测是否有更新的版本,从而确保您始终使用最新版本。
  4. 保存 Podfile
  5. 打开一个终端,然后转到包含 Podfile 的目录:

    cd <path-to-project>
  6. 运行 pod install 命令。此操作会安装 Podfile 中指定的 API 及其可能具有的任何依赖项。

    pod install
  7. 关闭 Xcode,然后打开(双击)您项目的 .xcworkspace 文件以启动 Xcode。从此刻开始,您必须使用 .xcworkspace 文件打开项目。

如需更新现有项目的 API,请按以下步骤操作:

  1. 打开终端并转到包含 Podfile 的项目目录。
  2. 运行 pod update 命令。这会将 Podfile 中指定的所有 API 更新到最新版本。

手动安装

本指南介绍如何将包含 Places SDK for iOS 的 XCFramework 手动添加到您的项目中,并在 Xcode 中配置构建设置。XCFramework 是一个可在多个平台(包括使用 Apple Silicon 的机器)上使用的二进制软件包。

  1. 下载以下 SDK 二进制文件和资源文件:
  2. 解压缩文件以访问 XCFramework 和资源。
  3. 启动 Xcode,并打开现有的项目或创建新项目。如果您刚开始接触 iOS 开发,请创建一个新项目,然后选择 iOS App template
  4. 移除项目中之前版本的任何地图捆绑包。
  5. 打开“常规”标签页。将以下 XCFramework 拖动到 Frameworks, Libraries, and Embedded Content 下的项目中。请务必选择不嵌入
    • GooglePlaces.xcframework
  6. GooglePlaces.bundle 从您下载的 GooglePlacesResources 中拖出
  7. GooglePlaces.bundle 从您下载的 GooglePlacesResources 复制到 Xcode 项目的顶级目录中。确保出现提示时,选择 Copy items into destination group's folder
  8. 从项目导航器中选择您的项目,然后选择应用的目标。
  9. 打开 Build Phases 标签页。在将二进制文件与库相关联中,添加以下框架和库:
    • CoreGraphics.framework
    • CoreLocation.framework
    • libc++.tbd
    • libz.tbd
    • QuartzCore.framework
    • UIKit.framework
  10. 选择您的项目(而不是特定目标),并打开“Build Settings”(构建设置)标签页。Linking - General -> Other Linker Flags(链接 - 常规 -> 其他链接器标记)部分中,将 -ObjC 添加到“Debug”和“Release”。如果看不到这些设置,请将 Build Settings 栏中的过滤条件从 Basic 更改为 All

GooglePlacesSwift

您可以使用 Swift Package Manager、CocoaPods 和手动安装 GooglePlacesSwift(预览版)SDK。所有流程中的安装步骤与 Places SDK for iOS 所述的步骤相同,但存在以下差异:

例如,如果使用 CocoaPods,则修改后的 Podfile 将如下所示:

source 'https://github.com/CocoaPods/Specs.git'

platform :ios, '15.3'

target 'YOUR_APPLICATION_TARGET_NAME_HERE' do
  pod 'GooglePlacesSwift', '0.1.0'
end

第 3 步:检查 Apple 隐私清单文件

Apple 要求针对 App Store 中的应用提供应用隐私权详细信息。如需了解最新动态和更多信息,请访问 Apple App Store 隐私权详细信息页面

Apple 隐私清单文件包含在 SDK 的资源包中。如需验证是否已包含 Privacy 清单文件并检查其内容,请为您的应用创建归档,并根据该归档生成隐私报告

第 4 步:将 API 密钥添加到您的应用

在下例中,请将 YOUR_API_KEY 替换为您的 API 密钥。

Swift

按照以下方法向 AppDelegate.swift 添加 API 密钥:

  • 添加以下 import 语句:
    import GooglePlaces
  • 将以下内容添加到您的 application(_:didFinishLaunchingWithOptions:) 方法中,并将 YOUR_API_KEY 替换为您的 API 密钥:
    GMSPlacesClient.provideAPIKey("YOUR_API_KEY")

Objective-C

按照以下方法向 AppDelegate.m 添加 API 密钥:

  • 添加以下 import 语句:
    @import GooglePlaces;
  • 将以下内容添加到您的 application:didFinishLaunchingWithOptions: 方法中,并将 YOUR_API_KEY 替换为您的 API 密钥:
    [GMSPlacesClient provideAPIKey:@"YOUR_API_KEY"];

GooglePlacesSwift

按照以下方法向 AppDelegate.swift 添加 API 密钥:

  • 添加以下 import 语句:
    import GooglePlacesSwift
  • 将以下内容添加到您的 application(_:didFinishLaunchingWithOptions:) 方法中,并将 YOUR_API_KEY 替换为您的 API 密钥:
    PlacesClient.shared.provideAPIKey("YOUR_API_KEY")

第 5 步:开始编写代码

以下代码示例演示了如何获取当前地点。

Swift

  import GooglePlaces
  import UIKit

  class GetStartedViewController : UIViewController {

    // Add a pair of UILabels in Interface Builder, and connect the outlets to these variables.
    @IBOutlet private var nameLabel: UILabel!
    @IBOutlet private var addressLabel: UILabel!

    private var placesClient: GMSPlacesClient!

    override func viewDidLoad() {
      super.viewDidLoad()
      placesClient = GMSPlacesClient.shared()
    }

    // Add a UIButton in Interface Builder, and connect the action to this function.
    @IBAction func getCurrentPlace(_ sender: UIButton) {
      let placeFields: GMSPlaceField = [.name, .formattedAddress]
      placesClient.findPlaceLikelihoodsFromCurrentLocation(withPlaceFields: placeFields) { [weak self] (placeLikelihoods, error) in
        guard let strongSelf = self else {
          return
        }

        guard error == nil else {
          print("Current place error: \(error?.localizedDescription ?? "")")
          return
        }

        guard let place = placeLikelihoods?.first?.place else {
          strongSelf.nameLabel.text = "No current place"
          strongSelf.addressLabel.text = ""
          return
        }

        strongSelf.nameLabel.text = place.name
        strongSelf.addressLabel.text = place.formattedAddress
      }
    }
  }

  

Objective-C

  #import "GetStartedViewController.h"
  @import GooglePlaces;

  @interface GetStartedViewController ()
  // Add a pair of UILabels in Interface Builder and connect the outlets to these variables
  @property (weak, nonatomic) IBOutlet UILabel *nameLabel;
  @property (weak, nonatomic) IBOutlet UILabel *addressLabel;
  @end

  @implementation GetStartedViewController {
    GMSPlacesClient *_placesClient;
  }

  - (void)viewDidLoad {
    [super viewDidLoad];
    _placesClient = [GMSPlacesClient sharedClient];
  }

  // Add a pair of UILabels in Interface Builder and connect the outlets to these variables.
  - (IBAction)getCurrentPlace:(UIButton *)sender {
    GMSPlaceField placeFields = (GMSPlaceFieldName | GMSPlaceFieldFormattedAddress);

    __weak typeof(self) weakSelf = self;
    [_placesClient findPlaceLikelihoodsFromCurrentLocationWithPlaceFields:placeFields callback:^(NSArray<GMSPlaceLikelihood *> * _Nullable likelihoods, NSError * _Nullable error) {
      __typeof__(self) strongSelf = weakSelf;
      if (strongSelf == nil) {
        return;
      }

      if (error != nil) {
        NSLog(@"An error occurred %@", [error localizedDescription]);
        return;
      }

      GMSPlace *place = likelihoods.firstObject.place;
      if (place == nil) {
        strongSelf.nameLabel.text = @"No current place";
        strongSelf.addressLabel.text = @"";
        return;
      }

      strongSelf.nameLabel.text = place.name;
      strongSelf.addressLabel.text = place.formattedAddress;
    }];
  }

  @end
  

GooglePlacesSwift

  struct ContentView: View {
    @State var place: Place?

    var body: some View {
      Button("Get Place") {
        // A hotel in Saigon with an attribution.
        let placeID = "ChIJV4k8_9UodTERU5KXbkYpSYs"
        let fetchPlaceRequest = FetchPlaceRequest(
          placeID: placeID,
          placeProperties: [.displayName, .formattedAddress]
        )
        Task {
          switch await placesClient.fetchPlace(with: fetchPlaceRequest) {
          case .success(let place):
            self.place = place
          case .failure(let placesError):
            // Handle error
        }
      Text(swiftPlace?.displayName ?? "No place yet")
        .padding()
      Text(swiftPlace?.formattedAddress ?? "No place yet")
        .padding()
    }
  }
  

后续步骤

配置项目后,您可以浏览示例应用