将地图添加到您的 iOS 应用 (Swift)

1. 准备工作

此 Codelab 会教您如何开始使用 Google Maps Platform 通过 Swift 构建 iOS 应用。您将构建一个 iOS 应用,用于执行以下操作:

  • 加载 Maps SDK for iOS 和 Maps SDK for iOS 实用程序库。
  • 显示以澳大利亚悉尼为中心的地图。
  • 显示悉尼周边 100 个地点的自定义标记。
  • 实现标记聚类。
  • 启用用户互动功能,这样,当用户点按标记时,能够重新设置中心并在地图上绘制圆形区域。

iOS 应用中带有标记的地图

前提条件

  • 具备 Swift 和 iOS 开发方面的基础知识。

学习内容

  • 加载 Maps SDK for iOS 和 Google Maps SDK for iOS 实用程序库。
  • 加载地图。
  • 使用标记、自定义标记和标记聚类。
  • 使用 Maps SDK for iOS 事件系统提供用户互动功能。
  • 以编程方式控制地图相机。
  • 在地图上绘图。

所需条件

若要完成此 Codelab,您需要以下帐号、服务和工具:

  • Xcode 12.0 或更高版本,目标 SDK 为 12.0 或更高版本。
  • 已安装的 CocoaPods。
  • 启用了结算功能的 Google Cloud Platform 帐号(请参阅下一步)。
  • 启用了 Maps SDK for iOS 的 Cloud Console 项目(请参阅下一步)。

2. 进行设置

若要完成下面的启用步骤,您需要启用 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 密钥。

快速入门

为了让您能尽快上手,我们在下面提供了一些起始代码,以帮助您顺利完成此 Codelab。

  1. 克隆代码库(如果您已安装 git)。
git clone https://github.com/googlemaps/codelab-maps-platform-101-swift.git

或者,点击获取代码以下载源代码。

  1. 下载代码后,请打开 /starter 目录下的 StarterApp 项目。此项目包含完成此 Codelab 所需的基本文件结构。您需要的所有内容均位于 /starter/StarterApp 目录下。

若要查看正在运行的完整解决方案代码,请在 /solution/SolutionApp 目录下查看完整代码。

3. 安装 Maps SDK for iOS

要使用 Maps SDK for iOS,第一步是安装所需的依赖项。此过程有两个步骤:通过 Cocoapods 依赖项管理器安装 Maps SDK for iOS 和 Maps SDK for iOS 实用程序库,和向 SDK 提供 API 密钥。

  1. 将 Maps SDK for iOS 和 Maps SDK for iOS 实用程序库添加到 Podfile。

此 Codelab 会同时使用 Maps SDK for iOS 和 Maps iOS 实用程序库,前者提供 Google 地图的所有核心功能,后者提供各种实用程序(包括标记聚类)丰富您的地图内容。

首先,在 Xcode(或您首选的文本编辑器)中打开 Podfile,并更新该文件,使之在注释 # Pods for StarterApp 下添加 Maps SDK for iOS 和实用程序库依赖项:

pod 'GoogleMaps', '6.1.0'
pod 'Google-Maps-iOS-Utils', '3.4.0'

如需获取最新版 SDK 和相关维护指南,请参阅 Maps SDK for iOS 版本文档。

您的 Podfile 应如下所示:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '12.0'

target 'StarterApp' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for StarterApp
  pod 'GoogleMaps', '6.1.0'
  pod 'Google-Maps-iOS-Utils', '3.4.0'
end
  1. 安装 Maps SDK for iOS 和 Maps SDK for iOS 实用程序库 Pod。

如需安装依赖项,请通过命令行在 /starter 目录下运行 pod install。CocoaPods 会自动下载依赖项并创建 StarterApp.xcworkspace。

  1. 安装依赖项后,请从 /starter 目录运行 open StarterApp.xcworkspace,以在 Xcode 中打开该文件,然后通过按下 Command+R 在 iPhone 模拟器中运行应用。如果一切设置正确无误,模拟器将启动并显示黑屏。不用担心,因为您尚未构建任何内容,所以黑屏是正常现象!
  2. 在 AppDelegate.swift 中导入 SDK。

现在您已安装了依赖项,可以向 SDK 提供 API 密钥了。首先,导入 Maps SDK for iOS 作为依赖项,只需将以下代码放在 import UIKit import 语句下方即可:

import GoogleMaps
  1. 在 application: didFinishLaunchingWithOptions: 中对 GMSServices 调用 provideAPIKey,将 API 密钥传递给 iOS SDK
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    // Override point for customization after application launch.
    GMSServices.provideAPIKey("YOUR_API_KEY")

    return true
  }

更新后的 AppDelegate.swift 文件现在应如下所示:

import UIKit
import GoogleMaps

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
  var window: UIWindow?

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    // Override point for customization after application launch.
    GMSServices.provideAPIKey("YOUR_API_KEY")

    return true
  }

}

将 YOUR_API_KEY 替换为您在 Cloud Console 中创建的 API 密钥。

现在您已安装好依赖项并提供了 API 密钥,可以开始调用 Maps SDK for iOS 了。

4. 显示地图

是时候显示您的第一个地图了!

Maps SDK for iOS 中最常用的部分是 GMSMapView 类,它提供了许多可让您创建和操纵地图实例的方法。具体步骤如下:

  1. 打开 ViewController.swift。

您将在此处完成此 Codelab 的剩余操作。请注意,我们已为您弃用了视图控制器的 loadView 和 viewDidLoad 生命周期事件。

  1. 通过在文件顶部添加以下代码,导入 Maps SDK for iOS:
import GoogleMaps
  1. 声明用于存储 GMSMapView 的实例变量 ViewController。

在此 Codelab 的整个过程中,GMSMapView 实例是您使用的主要对象,您将在各种视图控制器生命周期方法中引用该对象,并在其上执行操作。若要提供该实例,请更新 ViewController 的实现,以声明一个用于存储该实例的实例变量:

class ViewController: UIViewController {

  private var mapView: GMSMapView!

  ...
}
  1. 在 loadView 中,创建 GMSCameraPosition 实例。

GMSCameraPosition 可定义地图的中心位置以及显示时的缩放级别。以下代码会调用 cameraWithLatitude:longitude:zoom: 方法,将地图中心设为澳大利亚悉尼,纬度为 -33.86,经度为 151.20,缩放级别为 12:

let camera:GMSCameraPosition = GMSCameraPosition.camera(withLatitude: -33.86, longitude: 151.20, zoom: 12)
  1. 在 loadView 中,创建 GMSMapView 的实例,以实例化地图。

要创建新的地图实例,请调用 GMSMapView(frame: CGRect, camera: GMSCameraPosition)。请注意帧是如何设为 CGRect.zero 的,这是一个来自 iOS CGGeometry 库的全局变量,会指定一个宽度为 0、高度为 0 且位于视图控制器内 (0,0) 位置的帧。相机已设在您刚刚创建的相机位置上。

若要显示地图,接下来需要将视图控制器的根视图设置为 mapView,这样地图就会以全屏方式显示。

    mapView = GMSMapView(frame: .zero, camera: camera)
    self.view = mapView
  1. 将 GMSMapViewDelegate 设置为视图控制器。

实现后,通过地图视图委托,您可以处理来自 GMSMapView 实例上用户互动的事件,后续步骤中您会需要使用这些事件。

首先,更新 ViewController 的接口,以遵循 GMSMapViewDelegate: 的协议

class ViewController: UIViewController, GMSMapViewDelegate

接下来,在 loadView 函数中添加以下代码,以将 GMSMapViewDelegate 设置为 ViewController。

    mapView.delegate = self

现在,在 iOS 模拟器中重新加载应用(通过按下 Command+R),地图应该如图 1 所示!

显示 Google 地图的 iOS 应用

图 1. 显示 Google 地图的 iOS 应用。

回顾一下,在此步骤中,您通过创建 GMSMapView 实例,显示了一个以澳大利亚悉尼市为中心的地图。

您的 ViewController.swift 文件现在应如下所示:

import UIKit
import GoogleMaps

class ViewController: UIViewController, GMSMapViewDelegate {

  private var mapView: GMSMapView!

  override func loadView() {

    // Load the map at set latitude/longitude and zoom level
    let camera:GMSCameraPosition = GMSCameraPosition.camera(withLatitude: -33.86, longitude: 151.20, zoom: 11)

    mapView = GMSMapView(frame: .zero, camera: camera)
    self.view = mapView
    mapView.delegate = self
  }

  override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
  }

}

5. 设置地图样式(可选)

您可以使用云端地图样式设置自定义地图样式。

创建地图 ID

如果您尚未使用关联的地图样式创建地图 ID,请参阅地图 ID 指南完成以下步骤:

  1. 创建地图 ID。
  2. 将地图 ID 与地图样式相关联。

为您的应用添加地图 ID

若要使用您在上一步中创建的地图 ID,请打开 ViewController.swift 文件,然后在 loadView 方法中创建一个 GMSMapID 对象并为其提供地图 ID。接下来,通过提供 GMSMapID 对象作为参数来修改 GMSMapView 实例化。

ViewController.swift

  override func loadView() {

    // Load the map at set latitude/longitude and zoom level
    let camera:GMSCameraPosition = GMSCameraPosition.camera(withLatitude: -33.86, longitude: 151.20, zoom: 11)
    let mapID = GMSMapID(identifier: "YOUR_MAP_ID")

    mapView = GMSMapView(frame: .zero, mapID: mapID, camera: camera)
    self.view = mapView
    mapView.delegate = self
  }

完成上述操作后,运行应用,以您选择的样式查看您的地图!

6. 向地图添加标记

虽然开发者可以借助 Maps SDK for iOS 执行很多操作,但是在地图上添加标记绝对是最受欢迎的操作。标记可用于在地图上标识出特定地点,并且是用来处理用户互动的常见界面元素。如果您之前使用过 Google 地图,那么可能熟悉默认标记,如图 2 中的红色图钉所示:

带有红色标记的地图

图 2. 带有红色标记的地图。

此步骤演示了如何使用 GMSMarker 类在地图上添加标记。

请注意,在通过视图控制器的 loadView 生命周期事件中的上一步加载地图之前,您无法在地图上放置标记,因此您要在 viewDidLoad 生命周期事件中完成这些步骤,该事件会在视图(和地图)加载完成后调用。

  1. 定义 CLLocationCoordinate2D 对象。

CLLocationCoordinate2D 是 iOS CoreLocation 库提供的结构体,用于定义位于一组纬度和经度上的地理位置。若要开始创建您的第一个标记,请定义 CLLocationCoordinate2D 对象,并将纬度和经度设置为地图的中心位置。您可使用 camera.target.latitude 和 camera.target.longitude 属性从地图视图中访问地图中心的坐标。

    // Add a single marker with a custom icon
    let mapCenter = CLLocationCoordinate2DMake(mapView.camera.target.latitude, mapView.camera.target.longitude)
  1. 创建 GMSMarker 实例。

Maps SDK for iOS 提供 GMSMarker 类。每个 GMSMarker 实例都代表地图上的一个标记,且创建实例时,采取了调用 markerWithPosition: 并向实例传递 CLLocationCoordinate2D 对象以告知 SDK 应在地图何处放置标记的方式。

    let marker = GMSMarker(position: mapCenter)
  1. 设置自定义标记图标。

Google 地图的默认红色图钉标记非常不错,但对地图进行自定义也是如此!幸运的是,通过 Maps SDK for iOS 使用自定义标记非常简单。请注意,StarterApp 项目包含了一张名为“custom_pin.png”的图片,供您使用,但您可以使用自己想要的任何图片。

若要设置自定义标记,请将标记的 icon 属性设置为 UIImage 实例。

    marker.icon = UIImage(named: "custom_pin.png")
  1. 将标记渲染到地图上。

您的标记已创建完毕,但尚未显示在地图上。为此,请将 GMSMarker 实例的 map 属性设置为 GMSMapView 实例。

    marker.map = mapView

现在重新加载应用,即可看到您的第一个带标记的地图,如图 3 所示!

包含 Google 地图(中心位置带有红色标记)的 iOS 应用

图 3. 包含 Google 地图(中心位置带有红色标记)的 iOS 应用。

回顾一下,在此部分中,您创建了 GMSMarker 类的实例,并将其应用到地图视图,成功地在地图上显示出标记。ViewController.swift 中更新后的 viewDidLoad 生命周期事件现在应如下所示:

  override func viewDidLoad() {
    super.viewDidLoad()

    // Add a single marker with a custom icon
    let mapCenter = CLLocationCoordinate2DMake(mapView.camera.target.latitude, mapView.camera.target.longitude)
    let marker = GMSMarker(position: mapCenter)

    marker.icon = UIImage(named: "custom_pin.png")
    marker.map = mapView
  }

7. 启用标记聚类

如果您使用多个标记或标记彼此靠得很近,您可能会遇到如下问题:标记重叠或看起来很拥挤,导致用户体验不佳。例如,如果两个标记彼此靠得很近,那么您可能会遇到如图 4 中所示的情况:

两个彼此靠得很近的标记

图 4. 两个彼此靠得很近的标记。

这正是标记聚类的用武之地。标记聚类是另一种经常实现的地图项,可将临近的标记组合为单个图标,并且该图标能够随缩放级别而改变,如图 5 所示:

多个标记聚类为单个图标的示例

图 5. 多个标记聚类为单个图标的示例。

标记聚类算法会将地图的可见区域划分为网格,然后对位于同一单元格的图标进行聚类。Google Maps Platform 团队创建了一个实用的开源实用程序库,名为 Google Maps SDK for iOS 实用程序库,除了许多其他功能之外,这个实用程序库还会自动为您处理标记聚类。如需详细了解标记聚类,请参阅 Google Maps Platform 文档,也可以在 GitHub 上查看 iOS 实用程序库的源代码。

  1. 向地图添加更多标记。

要了解标记聚类的实际运作情况,您需要在地图上放置大量标记。为了化繁为简,我们在 MarkerGenerator.swift 的入门级项目中提供了一个便利的标记生成器。

若要向地图添加指定数量的标记,请调用上一步代码下的视图控制器 viewDidLoad 生命周期中的 MarkerGenerator(near:count:).markerArray。该方法会在 CLLocationCoordinate2D 对象中指定坐标周围的随机位置创建 count 中指定的标记个数。在这种情况下,您可以将前面创建的 mapCenter 变量传递给该对象。系统会以 [GMSMarker] 形式返回标记。

    // Generate many markers
    let markerArray = MarkerGenerator(near: mapCenter, count: 100).markerArray

您可以在 markerArray 的定义之后添加以下几行代码,然后运行应用,以测试这种多标记视图的显示效果。请务必先注释掉以下几行代码,然后再执行后续步骤,即改用标记聚类器来管理标记的显示方式:

    // Comment the following code out if using the marker clusterer
    // to manage markers instead.
    for marker in markerArray {
      marker.map = mapView
    }
  1. 导入 Google Maps SDK for iOS 实用程序库。

若要将 Maps iOS 实用程序库作为依赖项添加到您的项目中,请将以下代码添加到 ViewController.swift 顶部的依赖项列表中:

import GoogleMapsUtils
  1. 配置标记聚类器。

要使用标记聚类器,您需要提供三项内容来配置其运行方式:聚类算法、图标生成器和渲染程序。聚类算法用于确定标记的聚类行为,例如要在同一聚类中添加的标记之间的距离。图标生成器会提供要在不同缩放级别使用的聚类图标。渲染程序可处理地图上聚类图标的实际渲染。

如果您愿意,也可以从头开始编写上述所有程序,不过 Maps iOS 实用程序库提供了默认实现来简化这一过程。添加以下代码:

    // Set up the cluster manager with a supplied icon generator and renderer.
    let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
    let iconGenerator = GMUDefaultClusterIconGenerator()
    let renderer = GMUDefaultClusterRenderer(mapView: mapView, clusterIconGenerator: iconGenerator)
  1. 创建 GMUClusterManager 实例。

GMUClusterManager 类可使用您指定的算法、图标生成器和渲染程序实现标记聚类。若要创建渲染程序并将其提供给地图视图,请先向 ViewController 实现添加实例变量,以存储聚类管理器实例:

class ViewController: UIViewController, GMSMapViewDelegate {

  private var mapView: GMSMapView!
  private var clusterManager: GMUClusterManager!
}

然后,在 viewDidLoad 生命周期事件中创建 GMUClusterManager 的实例:

    clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm, renderer: renderer)
  1. 添加标记并运行标记聚类器。

现在,您的标记聚类器实例已配置完毕,请调用 add(items:) 将要进行聚类的标记数组传递给聚类管理器,然后调用 cluster 来运行聚类器。

    clusterManager.setMapDelegate(self)
    clusterManager.add(markerArray)
    clusterManager.cluster()

现在,重新加载您的应用,您应该会看到大量标记都已进行了妥当的聚类,如图 6 中的示例所示。接下来,您可以在地图上进行双指张合和缩放操作,尝试不同的缩放级别,看看标记聚类随着您放大/缩小而调整的情况。

包含 Google 地图和已聚类标记的 iOS 应用

图 6. 包含 Google 地图和已聚类标记的 iOS 应用。

回顾一下,在此步骤中,您通过 Google Maps SDK for iOS 实用程序库配置了标记聚类器的实例,然后使用该实例对地图上的 100 个标记进行了聚类。ViewController.swift 中的 viewDidLoad 生命周期事件现在应如下所示:

  override func viewDidLoad() {
    super.viewDidLoad()

    // Add a single marker with a custom icon
    let mapCenter = CLLocationCoordinate2DMake(mapView.camera.target.latitude, mapView.camera.target.longitude)
    let marker = GMSMarker(position: mapCenter)

    marker.icon = UIImage(named: "custom_pin.png")
    marker.map = mapView

    // Generate many markers
    let markerArray = MarkerGenerator(near: mapCenter, count: 100).markerArray
    // Comment the following code out if using the marker clusterer
    // to manage markers instead.
    //    for marker in markerArray {
    //      marker.map = mapView
    //    }

    // Set up the cluster manager with a supplied icon generator and renderer.
    let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
    let iconGenerator = GMUDefaultClusterIconGenerator()
    let renderer = GMUDefaultClusterRenderer(mapView: mapView, clusterIconGenerator: iconGenerator)
    clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm, renderer: renderer)

    clusterManager.setMapDelegate(self)
    clusterManager.add(markerArray)
    clusterManager.cluster()
  }

8. 添加用户互动

您现在有一个精美地图,不仅显示着各种标记,还使用了标记聚类。在此步骤中,您将使用之前已设为视图控制器的 GMSMapViewDelegate,对用户互动添加一些额外处理,以改善地图的用户体验。

Maps SDK for iOS 提供通过地图视图委托实现的全面事件系统,其中包含可让您在发生各种用户互动时执行代码的事件处理脚本。例如,MapView 委托包含各种方法,可让您触发互动(例如,用户点击地图和标记、平移地图的视图、放大和缩小等)的代码执行。

在此步骤中,您需要以编程方式平移地图,以将地图中心设置为用户点按的任何标记。

  1. 实现标记点按监听器。

每当用户点按您之前创建的其中一个标记,以及点按标记聚类(在内部会将标记聚类作为 GMSMarker 实例来实现)时,系统就会调用 mapView(_:didTap:)。

若要实现事件监听器,请先在右侧大括号前的 ViewController.swift 底部将事件监听器移出。

  func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {

    return false
  }

请注意,该方法将返回 false。此操作会指示 iOS SDK 在执行完事件处理脚本代码后继续执行默认的 GMSMarker 功能,例如显示信息窗口(如果已配置)。

  1. 处理点按事件,并在用户点按标记或标记聚类时,为相机添加动画效果以重新设置地图中心。

mapView(_:didTap:) 在被调用时会传递已点按的 GMSMarker 实例,以便您在代码中对其进行处理。您可以使用该实例重新设置地图的中心,只需从事件处理脚本内部对地图视图调用 animate(toLocation:),并向其传递 position 属性中标记实例的位置即可。

    // Animate to the marker
    mapView.animate(toLocation: marker.position)
  1. 用户点按标记聚类时,放大所点按的标记聚类。

一种常见的用户体验模式是,用户点按标记聚类时,放大所点按的标记聚类。这样一来,当聚类在较低的缩放级别展开时,用户可以查看已聚类的标记。

如前所述,标记聚类图标实际上是带有自定义图标的 GMSMarker 的实现。那么该如何判断用户是否点按了标记或标记聚类呢?当标记聚类器管理器创建新的聚类图标时,它会实现 GMSMarker 实例以遵循名为 GMUCluster. 的协议。您可以使用条件语句来检查传递到事件处理脚本的标记是否遵循了此协议。

在以编程方式获知用户已点按聚类后,您就可以对地图视图实例调用 animate(toZoom:),并将缩放级别设置为当前级别加 1。当前的缩放级别可在 camera.zoom 属性中的 mapView 实例上使用。

另外,请注意以下代码是如何返回 true 的。这会告知事件处理脚本您已完成事件的处理,以及不要执行处理脚本中的任何其他代码了。这样做的原因之一是防止底层 GMSMarker 对象执行其余的默认行为,例如显示信息窗口,这些行为在用户点按聚类图标时并没有太大意义。

    // If the tap was on a marker cluster, zoom in on the cluster
    if let _ = marker.userData as? GMUCluster {
      mapView.animate(toZoom: mapView.camera.zoom + 1)
      return true
    }

现在重新加载应用,并点按一些标记和标记聚类。无论您点按其中哪一种,地图都会将所点按的元素设置为地图中心。当用户点按标记聚类时,地图还会放大一个级别,同时标记聚类将展开,以显示归属此聚类的标记。

回顾一下,在此步骤中,您实现了标记点按监听器,并处理了该事件以将点按的元素重设为地图中心,且在所点按的元素是标记聚类图标的情况下进行放大。

您的 mapView(_:didTap:) 方法应如下所示:

  func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {

    // Animate to the marker
    mapView.animate(toLocation: marker.position)

    // If the tap was on a marker cluster, zoom in on the cluster
    if let _ = marker.userData as? GMUCluster {
      mapView.animate(toZoom: mapView.camera.zoom + 1)
      return true
    }

    return false
  }

9. 在地图上绘制

到目前为止,您已经创建了悉尼地图,在 100 个随机地点显示了标记并处理了用户互动。在此 Codelab 的最后一步中,您将使用 Maps SDK for iOS 的绘图功能,为您的地图体验添加其他实用地图项。

想象一下,此地图将供希望探索悉尼这座城市的用户使用。实用地图项旨在直观展示所点击标记周围一定半径的区域。这样,用户便可以轻松了解从所点击的标记可以轻松步行至其他哪些目的地。

iOS SDK 包括一组用于在地图上绘制形状(例如方形、多边形、线条和圆形)的函数。在此步骤中,您将渲染一个圆形,当用户点击标记时,在该标记周围显示半径为 800 米(大约半英里)的区域。

  1. 将 circle 实例变量添加到 ViewController 的实现中。

此实例变量用于保存最近绘制的圆形,以便在绘制其他圆形之前可将其销毁。毕竟,它对用户没有太大帮助,并且如果每个点按的标记周围都有绘制的圆形,外观上也不美观!

为此,请使用如下所示的代码更新 ViewController 的实现:

class ViewController: UIViewController, GMSMapViewDelegate {

  private var mapView: GMSMapView!
  private var clusterManager: GMUClusterManager!
  private var circle: GMSCircle? = nil
  ...
}
  1. 在用户点按标记时绘制圆形区域。

在 return false 语句正上方的 mapView(_:didTap:) 方法底部,添加此处所示代码来创建 iOS SDK 的 GMSCircle 类的实例,以便绘制一个新的半径为 800 米的圆形,具体方法是调用 GMSCircle(position:radius:) 并向其传递所点按标记的位置,一如您在上文重新设置地图中心时的操作。

    // Draw a new circle around the tapped marker
    circle = GMSCircle(position: marker.position, radius: 800)
  1. 设置圆形样式。

默认情况下,GMSCircle 会绘制一个带黑色描边和透明填充效果的圆形。这非常适合显示半径,但外观并不美观,而且有点不太显眼。接下来,通过向圆形的 fillColor 属性分配 UIColor 的方式,为圆形提供填充色,以改善样式。此处所示代码会添加透明度为 50% 的灰色填充效果:

    circle?.fillColor = UIColor(red: 0.67, green: 0.67, blue: 0.67, alpha: 0.5)
  1. 对地图上的圆形进行渲染。

和前面创建标记时一样,创建 GMSCircle 实例并不会使圆形显示在地图上。若要显示圆形,请将地图视图实例分配给圆形的 map 属性。

    circle?.map = mapView
  1. 移除之前渲染的所有圆形。

如前所述,一味在地图上添加圆形并不能带来良好的用户体验。若要移除上一个点按事件所渲染的圆形,请将 circle 的 map 属性设置为 mapView(_:didTap:) 顶部的 nil。

    // Clear previous circles
    circle?.map = nil

重新加载应用,然后点按某个标记。每当用户点按标记时,您都应该会看到一个新绘制的圆形,并且之前渲染的所有圆形均已移除,如图 7 所示。

在点按的标记周围绘制的一个圆形

图 7. 在点按的标记周围绘制的一个圆形。

回顾一下,在此步骤中,您使用了 GMSCircle 类,在每次用户点按标记时渲染圆形。

mapView(_:didTap:) 方法应如下所示:

  func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {

    // Clear previous circles
    circle?.map = nil

    // Animate to the marker
    mapView.animate(toLocation: marker.position)

    // If the tap was on a marker cluster, zoom in on the cluster
    if let _ = marker.userData as? GMUCluster {
      mapView.animate(toZoom: mapView.camera.zoom + 1)
      return true
    }

    // Draw a new circle around the tapped marker
    circle = GMSCircle(position: marker.position, radius: 800)
    circle?.fillColor = UIColor(red: 0.67, green: 0.67, blue: 0.67, alpha: 0.5)
    circle?.map = mapView
    return false
  }

10. 恭喜

您已成功构建了一个包含互动式 Google 地图的 iOS 应用。

所学内容

后续步骤

  • 探索包含各种示例和演示的 maps-sdk-for-ios-samples GitHub 代码库或创建分支,以便汲取更多灵感
  • 通过更多 Swift Codelab 进行学习,了解如何使用 Google Maps Platform 构建 iOS 应用
  • 请回答下面的问题,帮助我们为您制作最为有用的内容:

您还想学习哪些 Codelab?

地图上的数据可视化 更多关于自定义地图样式的信息 在地图中构建 3D 交互

上面没有列出您希望了解的 Codelab?没关系,请在此处通过创建新问题的方式申请 Codelab。