地圖和定位相關(guān)研究(一) —— Google Maps的集成(一)

版本記錄

版本號 時間
V1.0 2020.03.14 星期六

前言

定位和地圖是很多App中必有的功能,這里單獨抽出來模塊一起學(xué)習(xí)和探討。感興趣的可以多指正,大家一起進步。對于蘋果地圖框架MapKit我已經(jīng)單獨列出來了 - MapKit框架詳細解析 - 會隨時更新。感興趣的可以看下。這里只說下三方地圖SDK的相關(guān)集成和其他相關(guān)問題。

開始

差不多一個多月沒更新了,是狀態(tài)有點差,在慢慢調(diào)節(jié),謝謝大家繼續(xù)支持!

首先看下主要內(nèi)容

您將學(xué)習(xí)如何使用Google Maps iOS SDK制作應(yīng)用程序,以搜索附近的飲食場所或雜貨店。

下面看下寫作環(huán)境

Swift 5, iOS 13, Xcode 11

在2012年之前,Google Maps是所有iOS設(shè)備的地圖引擎。 那年,蘋果公司通過內(nèi)部地圖引擎MapKit取代了Google Maps,從而在iOS 6中做出了巨大的改變。

幾個月后,Google發(fā)布了自己的iOS獨立Google Maps應(yīng)用程序,以及面向開發(fā)人員的Google Maps iOS SDK

MapKitGoogle Maps iOS SDK都有各自的優(yōu)缺點。 您必須決定哪一種最適合您的用例。 如果您決定使用Google Maps SDK,則本教程適合您!

在本教程中,您將構(gòu)建一個名為Feed Me的應(yīng)用程序,該應(yīng)用程序?qū)@取用戶的當前位置,并搜索附近的飲食場所或雜貨店。 在此過程中,您將學(xué)習(xí)如何使用Google Maps iOS SDK

  • 獲取用戶的位置。
  • 顯示街道地址。
  • 顯示附近的搜索結(jié)果。
  • 提供找到的地方的額外相關(guān)信息。

打開已有工程Feed Me.xcworkspace。

熟悉一下該項目。 需要注意的重要事項是:

  • MapViewController.swift:此項目的主視圖控制器,也是您將在本教程中修改的唯一視圖控制器。
  • GoogleDataProvider.swift:包裝器類,用于進行Google API調(diào)用。 您將在本教程的后面部分中回顧其中包含的方法。
  • GooglePlace.swift:為Google返回的地方結(jié)果建模。
  • MarkerInfoView.swiftUIView的子類,用于顯示位置的詳細信息。 它帶有一個匹配的.xib文件。

在開始編碼之前,請構(gòu)建并運行您的應(yīng)用程序。 您會看到以下屏幕:

現(xiàn)在,您會看到的是一個空白屏幕,中間有一個大頭針。 接下來,按導(dǎo)航欄右側(cè)的操作按鈕以查看TypesTableViewController屏幕:

目前,所有這些都可以在應(yīng)用中看到。 您可以添加一些魔法!


Creating the API Key

您需要做的第一件事是使用Google Maps SDKGoogle API的API密鑰。 如果您還沒有Google帳戶,請創(chuàng)建一個(免費?。?,然后登錄Google Developers Console。

單擊Create以創(chuàng)建一個新項目,將您的項目命名為Feed Me,然后單擊Create

如果您的項目沒有立即顯示,請刷新頁面直到顯示出來。 在新創(chuàng)建的項目中,選擇Enable APIs and services

搜索并啟用以下API:

  • Maps SDK for iOS
  • Places API

在左側(cè)菜單面板的APIs & Services下,選擇Credentials。 單擊Create Credentials,然后單擊API key以創(chuàng)建密鑰:

您必須先添加實際的Google Maps iOS SDK,然后才能使用該密鑰。 因此,暫時保持窗口打開。


Adding the SDK

Pods項目中打開Podfile,然后在結(jié)尾上方添加以下內(nèi)容:

pod 'GoogleMaps', '~> 3.7.0'

接下來,打開終端并使用cd命令導(dǎo)航到包含Feed Me項目的目錄

cd ~/Path/To/Folder/Containing/Feed Me

輸入以下命令以安裝Google Maps iOS SDK

pod install

您應(yīng)該看到如下輸出:

Analyzing dependencies
Downloading dependencies
Installing GoogleMaps 3.7.0
Generating Pods project
Integrating client project

現(xiàn)在,您的項目中已有GoogleMaps。 CocoaPods使生活更加輕松!

打開AppDelegate.swift并將其內(nèi)容替換為以下內(nèi)容:

import UIKit
import GoogleMaps

//1
let googleApiKey = "ENTER_KEY_HERE"

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

  func application(
    _ application: UIApplication, 
    didFinishLaunchingWithOptions launchOptions: 
      [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    //2
    GMSServices.provideAPIKey(googleApiKey)
    return true
  }
}

這里有兩個新元素:

  • 1) 用來保存您的Google API密鑰的常量。 將ENTER_KEY_HERE替換為您先前創(chuàng)建的Google API密鑰。
  • 2) 使用GMSServices類方法ProvideAPIKey()使用API密鑰實例化Google Maps服務(wù)。

Creating the Map View

現(xiàn)在您已經(jīng)有了API密鑰,您可以注銷并關(guān)閉Google Developers Console窗口。

1. Adding a UIView

首先打開Main.storyboard來啟動Interface Builder。 找到MapViewController場景,然后將簡單的UIView從對象庫中拖到MapViewController視圖的大致中心。 使用View ? Show Library以顯示對象庫。

將視圖的背景顏色更改為淺灰色。 接下來,使用Editor ? Outline打開Document Outline,然后重新排列視圖層次結(jié)構(gòu),以便對象樹如下所示:

要將這個簡單的UIView變成GMSMapView,請選擇剛剛添加的視圖,然后通過從Utilities工具欄中選擇第三個選項卡來打開Identity inspector。 將視圖的Class更改為GMSMapView,如以下屏幕截圖所示:

你的MapViewController應(yīng)該如下所示:

2. Adding the Constraints for the Map View

接下來,您將添加一些約束以使地圖覆蓋整個屏幕。

Document Outline中選擇Map View,然后選擇Interface Builder窗口右下角的中間按鈕。 這是Pin按鈕。

確保未選中Constrain to margins(確保地圖將填充屏幕上的所有可用空間),并從父視圖的頂部,左側(cè),底部和右側(cè)添加0個空間約束。

您的Pin編輯器應(yīng)如下所示:

單擊Add 4 Constraints以將約束添加到地圖視圖。
您的MapViewController場景應(yīng)如下所示,其中灰色區(qū)域代表GMSMapView

3. Creating an Outlet for the Map View

在構(gòu)建和運行項目之前,請為地圖視圖添加IBOutlet。 為此,請使用鍵盤快捷鍵Command-Option-Control-Return調(diào)出助手編輯器。

Interface Builder中選擇地圖視圖,按住Control鍵,然后將一條線從地圖視圖拖到MapViewController.swift。 將會出現(xiàn)一個彈出窗口。 將連接類型設(shè)置為Outlet,將“名稱”設(shè)置為mapView。 將類型保留為GMSMapView并單擊Connect

這將在MapViewController.swift中創(chuàng)建一個GMSMapView屬性,并在Interface Builder中自動將其連接。 最后,在import UIKit之后,將以下內(nèi)容添加到文件頂部:

import GoogleMaps

構(gòu)建你將會看見一個地圖

您現(xiàn)在正在應(yīng)用中使用Google Maps iOS SDK。 但是,除了顯示基本地圖之外,您還可以做其他事情,對吧?下一步將是根據(jù)您的用戶所在位置自定義地圖。


Getting the Location

Feed Me就是尋找用戶附近的地方,而如果不獲取用戶的位置,您將無法做到這一點。

1. Adding MapViewController Extension

iOS使用代理通知用戶位置信息,你的下一步就是MapViewController遵循CLLocationManagerDelegate。

// MARK: - CLLocationManagerDelegate
//1
extension MapViewController: CLLocationManagerDelegate {
  // 2
  func locationManager(
    _ manager: CLLocationManager,
    didChangeAuthorization status: CLAuthorizationStatus
  ) {
    // 3
    guard status == .authorizedWhenInUse else {
      return
    }
    // 4
    locationManager.requestLocation()

    //5
    mapView.isMyLocationEnabled = true
    mapView.settings.myLocationButton = true
  }

  // 6
  func locationManager(
    _ manager: CLLocationManager,
    didUpdateLocations locations: [CLLocation]) {
    guard let location = locations.first else {
      return
    }

    // 7
    mapView.camera = GMSCameraPosition(
      target: location.coordinate,
      zoom: 15,
      bearing: 0,
      viewingAngle: 0)
  }

  // 8
  func locationManager(
    _ manager: CLLocationManager,
    didFailWithError error: Error
  ) {
    print(error)
  }
}

在此擴展程序中,您:

  • 1) 創(chuàng)建一個符合CLLocationManagerDelegateMapViewController擴展。
  • 2) 創(chuàng)建一個接受CLAuthorizationStatus參數(shù)的locationManager委托方法。 用戶授予或撤銷位置權(quán)限后,將調(diào)用此方法。
  • 3) 驗證用戶在使用該應(yīng)用程序時是否已授予您權(quán)限。
  • 4) 詢問位置經(jīng)理他們的位置。
  • 5) 添加用戶的位置指示器和位置按鈕。
  • 6) 創(chuàng)建另一個接受CLLocation數(shù)組的locationManager方法。 這在位置管理器接收到新的位置數(shù)據(jù)時執(zhí)行。
  • 7) 將地圖的攝像頭更新到用戶當前位置附近的中心。 GMSCameraPosition類匯總所有攝像機位置參數(shù),并將它們傳遞給地圖以進行顯示。
  • 8) 創(chuàng)建一個接受Error參數(shù)的第三個locationManager。 如果應(yīng)用程序引發(fā)錯誤,它將打印到控制臺,以便您可以處理它并防止應(yīng)用程序崩潰。

2. Creating an Instance of CLLocationManager

現(xiàn)在,您必須完成要求用戶位置的工作。

首先,將以下屬性添加到MapViewController

let locationManager = CLLocationManager()

這將添加并實例化名為locationManagerCLLocationManager屬性。

接下來,在擴展名中找到viewDidLoad()的定義,并將其替換為以下內(nèi)容:

override func viewDidLoad() {
  super.viewDidLoad()

  // 1
  locationManager.delegate = self

  // 2
  if CLLocationManager.locationServicesEnabled() {
    // 3
    locationManager.requestLocation()

    // 4
    mapView.isMyLocationEnabled = true
    mapView.settings.myLocationButton = true
  } else {
    // 5
    locationManager.requestWhenInUseAuthorization()
  }
}

這是這樣做的:

  • 1) 使MapViewController成為locationManager的委托。
  • 2) 檢查用戶先前是否已授權(quán)使用此應(yīng)用的位置服務(wù)。
  • 3) 向位置管理器詢問用戶的位置。
  • 4) 將isMyLocationEnabledmyLocationButton設(shè)置為true。 這會繪制一個淺藍色的點來指示用戶的位置,并添加一個按鈕以將地圖居中。
  • 5) 如果locationServicesEnabledfalse,則在使用應(yīng)用程序時請求訪問用戶的位置。

您已經(jīng)準備好檢查許可,但仍然需要先申請許可。 接下來,您將對其進行修復(fù)。

3. Asking for Permission to Get Location

打開項目導(dǎo)航器頂部的Feed Me項目,然后選擇Feed Me目標。 然后轉(zhuǎn)到Info選項卡,然后在Custom iOS Target Properties部分中選擇第一行。

按住Control鍵并單擊,然后從菜單中選擇Raw Keys & Values。 現(xiàn)在,單擊+圖標以添加新行。

NSLocationWhenInUseUsageDescription設(shè)置為鍵,選擇String作為類型,然后輸入以下文本作為值:

By accessing your location, this app can find good places to eat for you.

完成后,它將如下所示:

構(gòu)建并運行。 應(yīng)用加載后,系統(tǒng)會提示您一條警告,要求您提供位置權(quán)限。 點擊Allow While Using App。

現(xiàn)在,您會看到以您的位置為中心的地圖。 稍微滾動地圖,然后點擊右下角的Locate按鈕。 地圖再次以您的位置為中心。


Showing the Street Address

現(xiàn)在您已經(jīng)有了用戶的位置,現(xiàn)在可以顯示該位置的街道地址了。 Google Maps有一個對象可以做到這一點:GMSGeocoder。 這需要一個坐標并返回可讀的街道地址。

1. Creating the UI for the Address

首先,您將添加一些UI,以向用戶顯示地址。

打開Main.storyboard并將UILabel添加到MapViewController場景。 確保將UILabel添加到MapViewController的視圖中,而不是GMSMapView。

接下來,打開Attributes inspector,并為標簽設(shè)置以下屬性:

  • 居中對齊。
  • 行數(shù)為0。令人驚訝的是,這使label可以容納任意多行以適合文本。
  • 背景為白色,不透明度為85%

完成后,標簽的Attributes inspector和場景的Object Tree應(yīng)如下所示:

另外,請確保所有子視圖的排序如下:

最后,為標簽的左側(cè),底部和右側(cè)添加0個空間約束,如下所示:

這將標簽固定在屏幕的底部,并將其延伸到整個屏幕的寬度。

你的故事板場景應(yīng)該是這樣的:

接下來,為標簽創(chuàng)建一個outlet。

打開Assistant Editor并將其從Document Outline中的標簽拖拽到MapViewController.swift。將連接類型設(shè)置為Outlet,將名稱設(shè)置為addressLabel,然后單擊Connect。

這增加了一個屬性到你的MapViewController,你可以在你的代碼中使用:

@IBOutlet weak var addressLabel: UILabel!

2. Getting Address From a Coordinate

現(xiàn)在您已經(jīng)有了地址label,是時候獲取地址了。添加下面的方法到MapViewController:

func reverseGeocode(coordinate: CLLocationCoordinate2D) {
  // 1
  let geocoder = GMSGeocoder()

  // 2
  geocoder.reverseGeocodeCoordinate(coordinate) { response, error in
    guard 
      let address = response?.firstResult(), 
      let lines = address.lines 
      else {
        return
    }

    // 3
    self.addressLabel.text = lines.joined(separator: "\n")

    // 4
    UIView.animate(withDuration: 0.25) {
      self.view.layoutIfNeeded()
    }
  }
}

下面是每個注釋部分的功能:

  • 1) 創(chuàng)建GMSGeocoder對象,將緯度和經(jīng)度坐標轉(zhuǎn)換為街道地址。
  • 2) 請求地理編碼器對傳遞給方法的坐標進行反向地理編碼。然后驗證GMSAddress類型的響應(yīng)中是否有地址。這是GMSGeocoder返回地址的模型類。
  • 3) 將addressLabel的文本設(shè)置為地理編碼器返回的地址。
  • 4) 一旦地址被設(shè)置,在標簽的intrinsic content size的變化中產(chǎn)生動畫。

下一步是在用戶更改位置時保持地圖更新。

3. Updating the Address

每當用戶更改地圖上的位置時,您都希望調(diào)用上面的方法。為此,您將使用GMSMapViewDelegate。

添加另一個擴展到底部的MapViewController.swift如下:

// MARK: - GMSMapViewDelegate
extension MapViewController: GMSMapViewDelegate {
}

這將聲明MapViewController符合GMSMapViewDelegate。

接下來,將以下代碼添加到viewDidLoad():

mapView.delegate = self

這使得MapViewController成為地圖視圖的委托。

最后,將以下方法添加到新添加的擴展名中:

func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) {
  reverseGeocode(coordinate: position.target)
}

每當?shù)貓D停止移動并定位到新位置時,將調(diào)用此方法。然后調(diào)用反地理編碼到新位置并更新addressLabel的文本。

構(gòu)建和運行。您將在屏幕底部看到當前位置的地址—真實的或模擬的。

注意到這幅圖有什么問題嗎?

谷歌logo和定位按鈕隱藏在標簽后面!

4. Fixing the Street Address UI

幸運的是,GMSMapView為此提供了一個非常簡單的解決方案:填充padding。當您對地圖應(yīng)用內(nèi)邊距時,所有的視覺元素都將根據(jù)該內(nèi)邊距放置。

返回到reverseGeocodeCoordinate(_:)并在動畫塊之前添加這些行:

// 1
let labelHeight = self.addressLabel.intrinsicContentSize.height
let topInset = self.view.safeAreaInsets.top
self.mapView.padding = UIEdgeInsets(
  top: topInset,
  left: 0,
  bottom: labelHeight,
  right: 0)

現(xiàn)在,將動畫塊替換為:

UIView.animate(withDuration: 0.25) {
  //2
  self.pinImageVerticalConstraint.constant = (labelHeight - topInset) * 0.5
  self.view.layoutIfNeeded()
}

這做了兩件事:

  • 1) 在動畫塊之前向地圖的頂部和底部添加填充。頂部的內(nèi)邊距等于視圖頂部的安全區(qū)域間距,而底部的內(nèi)邊距等于標簽的高度。
  • 2) 通過調(diào)整地圖的垂直布局約束來更新定位大頭針的位置以匹配地圖的填充。

構(gòu)建并再次運行。這一次,一旦標簽變得可見,谷歌logolocate按鈕將移動到它們的新位置。

移動地圖,您將注意到,每當?shù)貓D定位到新位置時,地址都會發(fā)生變化。你將添加動畫來減弱這種效果。

將以下方法添加到GMSMapViewDelegate擴展中:

func mapView(_ mapView: GMSMapView, willMove gesture: Bool) {
  addressLabel.lock()
}

每當?shù)貓D開始移動時,都會調(diào)用此方法。它接收一個Bool,該Bool告訴您移動是源于用戶手勢(如滾動地圖),還是源于代碼。

如果移動來自用戶,您可以調(diào)用addressLabel上的lock()來給它一個加載動畫。

當有一個lock()時,也必須有一個相應(yīng)的unlock()。添加以下內(nèi)容作為傳遞給reverseGeocode(coordinate:)的閉包的第一行。它應(yīng)該正好在guard let之前:

self.addressLabel.unlock()

注意:要獲得lock()unlock()的完整實現(xiàn),請查看UIView+Extensions.swift。

構(gòu)建和運行。當您滾動地圖時,您將在地址標簽上看到一個加載動畫。


Finding Places

現(xiàn)在您已經(jīng)設(shè)置好了地圖,并掌握了用戶的位置,是時候為該用戶提供內(nèi)容了!

您將使用谷歌Google Places API來搜索用戶所在位置附近的餐飲場所。這是一個免費的web服務(wù)API,您可以使用它來查詢?nèi)魏谓o定點附近的場所、地理位置或其他感興趣的點。

1. Marking Locations on the Map

谷歌Maps iOS SDK為您提供了GMSMarker類來在地圖上標記位置。每個標記對象包含一個坐標和一個圖標圖像,并在添加它時在地圖上呈現(xiàn)。

對于這個應(yīng)用程序,您將提供每個標記的附加信息。為此,您將創(chuàng)建GMSMarker的一個子類。

創(chuàng)建一個新的Cocoa Touch類,命名為PlaceMarker,并使它成為GMSMarker的子類。確保您選擇了Swift作為該文件的語言。

PlaceMarker.swift的內(nèi)容替換為:

import UIKit
import GoogleMaps

class PlaceMarker: GMSMarker {
  // 1
  let place: GooglePlace

  // 2
  init(place: GooglePlace, availableTypes: [String]) {
    self.place = place
    super.init()

    position = place.coordinate
    groundAnchor = CGPoint(x: 0.5, y: 1)
    appearAnimation = .pop

    var foundType = "restaurant"
    let possibleTypes = availableTypes.count > 0 ? 
      availableTypes : 
      ["bakery", "bar", "cafe", "grocery_or_supermarket", "restaurant"]

    for type in place.types {
      if possibleTypes.contains(type) {
        foundType = type
        break
      }
    }
    icon = UIImage(named: foundType+"_pin")
  }
}

下面是這段代碼的作用:

  • 1) 將GooglePlace類型的屬性添加到PlaceMarker。
  • 2) 聲明一個新的指定初始化器,它接受GooglePlace和可用的位置類型。完全初始化一個PlaceMarker與位置,圖標圖像和錨標記的位置以及外觀動畫。

2. Searching for Nearby Places

接下來,添加兩個屬性到MapViewController:

let dataProvider = GoogleDataProvider()
let searchRadius: Double = 1000

你將使用在GoogleDataProvider.swift中定義的dataProvider。來調(diào)用谷歌Places Web API。您將使用searchRadius來設(shè)置與用戶的搜索距離。你把它設(shè)為1000米。

添加以下方法到MapViewController:

func fetchPlaces(near coordinate: CLLocationCoordinate2D){
  // 1
  mapView.clear()
  // 2
  dataProvider.fetchPlaces(
    near: coordinate,
    radius:searchRadius,
    types: searchedTypes
  ) { places in
    places.forEach { place in
      // 3
      let marker = PlaceMarker(place: place, availableTypes: self.searchedTypes)
      // 4
      marker.map = self.mapView
    }
  }
}

在這個方法中,你:

  • 1) 清除地圖上所有的標記。
  • 2) 使用dataProvidersearchRadius內(nèi)查詢谷歌,根據(jù)用戶選擇的類型進行篩選。
  • 3) 迭代完成閉包中返回的結(jié)果,并為每個結(jié)果創(chuàng)建一個PlaceMarker。
  • 4) 設(shè)置標記的地圖。這行代碼告訴地圖呈現(xiàn)標記。

這里有一個價值64,000美元的問題:什么時候調(diào)用這個方法?

答案是:當應(yīng)用程序啟動時。當你的用戶打開一個名為Feed Me的應(yīng)用程序時,他們將會看到一些吃飯的地方!

找到locationManager(_:didUpdateLocations:)并在末尾添加以下代碼行:

fetchPlaces(near: location.coordinate)

接下來,由于用戶可以更改要在地圖上顯示的位置類型,所以如果所選類型發(fā)生更改,您將更新搜索結(jié)果。

為此,找到typesController(_:didSelectTypes:)并在末尾添加以下代碼行:

fetchPlaces(near: mapView.camera.target)

最后,當用戶的位置發(fā)生變化時,您將為用戶提供獲取新位置的選項。

3. Adding a Refresh Map Option

打開Main.storyboar。將一個UIBarButtonItem從對象庫拖到MapViewController導(dǎo)航欄的左側(cè)。將按鈕的System Item更改為Refresh,如下所示:

打開助理編輯器并從刷新按鈕拖拽到MapViewController.swift。選擇Action并將該方法命名為refreshPlaces。在新添加的方法中插入如下代碼:

fetchPlaces(near: mapView.camera.target)

構(gòu)建和運行,你會看到位置大頭針彈出周圍的地圖。改變TypesTableViewController中的搜索類型,看看結(jié)果是如何變化的。

注意:如果您在更改搜索類型后沒有看到任何新的標記,這可能是由于谷歌的使用限制。等幾秒鐘,然后嘗試刷新。有關(guān)更多信息,請查看官方的谷歌Places使用限制文檔 - official Google Places usage limits documentation。

這些標記確實為地圖增加了一些顏色,但是如果沒有額外的數(shù)據(jù)來提供用戶關(guān)于固定位置的詳細信息,這些標記就沒有多大用處。

4. Showing Additional Place Information

將以下方法添加到MapViewController.swift中的GMSMapViewDelegate擴展中:

func mapView(
  _ mapView: GMSMapView, 
  markerInfoContents marker: GMSMarker
) -> UIView? {
  // 1
  guard let placeMarker = marker as? PlaceMarker else {
    return nil
  }

  // 2
  guard let infoView = UIView.viewFromNibName("MarkerInfoView") as? MarkerInfoView 
    else {
      return nil
  }

  // 3
  infoView.nameLabel.text = placeMarker.place.name
  infoView.addressLabel.text = placeMarker.place.address

  return infoView
}

每次點擊一個標記都會調(diào)用這個方法。如果您返回一個視圖,它將出現(xiàn)在標記的上方。如果返回nil,按鈕點擊什么也不做。

你要做的是:

  • 1) 您首先將點擊標記投射到PlaceMarker上。
  • 2)接下來,從它的nib創(chuàng)建一個MarkerInfoView。MarkerInfoView是本教程的入門項目附帶的一個UIView子類。
  • 3)然后將地名應(yīng)用到nameLabel,將地址應(yīng)用到addressLabel

一切都運行得很好,但是在完成應(yīng)用程序之前,您還有一個步驟來確保UI看起來是正確的。

5. Tidying up the UI

您需要確保位置大頭針不覆蓋信息窗口。為此,將以下方法添加到GMSMapViewDelegate擴展中:

func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
  mapCenterPinImage.fadeOut(0.25)
  return false
}

當用戶點擊一個標記時,這個方法隱藏定位針。該方法返回false,以指示您不希望在單擊標記時覆蓋將地圖居中的默認行為。

但是大頭針需要在某個時候重新出現(xiàn)。因此,將以下內(nèi)容添加到mapView(_:willMove:)的末尾:

if gesture {
  mapCenterPinImage.fadeIn(0.25)
  mapView.selectedMarker = nil
}

這將檢查動作是否源于用戶手勢。如果是這樣,則使用fadeIn(_:)來斷開位置pin。它還將地圖的selectedMarker設(shè)置為nil,以刪除當前呈現(xiàn)的infoView。

最后,將以下方法添加到GMSMapViewDelegate擴展中:

func didTapMyLocationButton(for mapView: GMSMapView) -> Bool {
  mapCenterPinImage.fadeIn(0.25)
  mapView.selectedMarker = nil
  return false
}

當用戶點擊Locate按鈕時,此方法將運行,從而使地圖以用戶的位置為中心。它還返回false,這樣就不會覆蓋按鈕的默認行為。

構(gòu)建和運行。選擇一個標記,你會看到位置淡出。滾動地圖,注意到infoView關(guān)閉并把大頭針帶回來:

就這樣,你做到了!你現(xiàn)在有一個功能齊全的谷歌地圖應(yīng)用程序。


Google Maps Versus Apple MapKit

當您考慮構(gòu)建自己的基于地圖的應(yīng)用程序時,您可能想知道是否應(yīng)該使用MapKit。下面是每個SDK的一些優(yōu)點,可以幫助您決定在您的情況下使用哪一個:

1. Advantages of Google Maps iOS SDK

  • SDK的頻繁更新。
  • 跨平臺(iOS和Android)應(yīng)用的統(tǒng)一體驗。
  • MapKit更詳細的地圖,特別是在美國以外的地方。

2. Advantages of Apple’s MapKit

  • 原生iOS。MapKit總是與iOS同步,并與開箱即用的Swift協(xié)同工作。
  • 更大的穩(wěn)定性。
  • 更好地與CoreLocationCoreAnimation集成。

谷歌Google Maps SDK太大了,不能包含在這個下載中,所以在運行構(gòu)建之前一定要運行pod install

本教程僅向您展示了谷歌Maps SDK的基本功能。還有很多東西要學(xué);您一定要查看這個SDK提供的其他優(yōu)秀特性的完整文檔full documentation。

例如,谷歌Maps iOS SDK還可以顯示方向、室內(nèi)地圖、覆蓋層、平鋪層和街景。為了獲得額外的權(quán)限,嘗試使用這些功能來增強Feed Me應(yīng)用程序。

后記

本篇主要講述了Google Maps的集成,感興趣的給個贊或者關(guān)注~~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容