MapKit框架詳細(xì)解析(二) —— 基本使用簡單示例(一)

版本記錄

版本號 時間
V1.0 2018.10.14 星期日

前言

MapKit框架直接從您的應(yīng)用界面顯示地圖或衛(wèi)星圖像,調(diào)出興趣點,并確定地圖坐標(biāo)的地標(biāo)信息。接下來幾篇我們就一起看一下這個框架。感興趣的看下面幾篇文章。
1. MapKit框架詳細(xì)解析(一) —— 基本概覽(一)

開始

首先看一下本文的寫作環(huán)境

Swift 4, iOS 11, Xcode 9

MapKit是iOS設(shè)備上非常有用的API,可以輕松顯示地圖,繪制位置,甚至在上面繪制路線和其他形狀。

此更新使用來自檀香山的公共藝術(shù)品數(shù)據(jù)。在本教程中,您將制作一個放大檀香山位置的應(yīng)用程序,并在地圖上繪制其中一件作品。 您將實施pin的標(biāo)注詳細(xì)信息按鈕以啟動Maps應(yīng)用程序,其中包含對藝術(shù)品的駕駛/步行路線。 然后,您的應(yīng)用程序?qū)腍onolulu數(shù)據(jù)門戶解析JSON文件,以提取公共藝術(shù)品對象,并在地圖上繪制它們。

在此過程中,您將學(xué)習(xí)如何將MapKit地圖添加到您的應(yīng)用程序,縮放到特定位置,解析使用Socrata Framework的政府?dāng)?shù)據(jù),創(chuàng)建自定義地圖annotations等等!

打開入門項目,其中包含JSON文件和一些圖像資源,但還沒有地圖!

打開Main.storyboard。 在File Inspector中,選中Use Safe Area Layout Guides框。 這將阻止您設(shè)置相對于已棄用的布局指南的約束,并停止deprecated警告。

Document Outline中,選擇Safe Area,以查看其上邊緣略低于視圖的上邊緣。 從Object library中,將MapKit View拖動到場景的上角,將其頂部邊緣與視圖頂部邊緣下方的藍(lán)色虛線對齊,然后拖動其右下角以與視圖的右下角相交。 使用Add New Constraints自動布局菜單(TIE戰(zhàn)斗機圖標(biāo))固定地圖視圖:取消選中Constrain to margins,然后將所有鄰值設(shè)置為0,并單擊Add 4 constraints

注意:通常情況下,您不必手動將地圖視圖拉伸到場景中 - 只需使用Add New Constraints菜單來固定其邊緣 - 但這在Xcode 9 beta中尚未使用?,F(xiàn)在Xcode 10都出來了,所以這個問題已經(jīng)不存在了。

接下來,將此行添加到ViewController.swift,就在import UIKit語句的下方:

import MapKit

Build并運行您的項目,您將擁有一個完全可縮放和可平移的地圖,使用Apple Maps顯示您當(dāng)前位置的大陸!

到目前為止這么好,嗯? 但是你不想開始查看整個世界的地圖 - 你想放大到一個特定的區(qū)域!

要控制地圖視圖,必須在ViewController.swift中為其創(chuàng)建outlet。

在故事板中,打開assistant editor:它應(yīng)該顯示ViewController.swift。

要創(chuàng)建outlet,請單擊Main.storyboard中的Map View,然后按住control - 拖動到ViewController類定義內(nèi)的空間:Xcode應(yīng)提示Insert Outlet or Outlet Collection。 釋放拖動,然后在彈出窗口中為outlet命名為mapView

Xcode將一個mapView屬性添加到ViewController類:您將使用它來控制地圖視圖顯示的內(nèi)容。


Setting Visible Area - 設(shè)置可見區(qū)域

切換回standard editor,在ViewController.swift中找到viewDidLoad(),并將以下內(nèi)容添加到方法的末尾:

// set initial location in Honolulu
let initialLocation = CLLocation(latitude: 21.282778, longitude: -157.829444)

您將使用它將地圖視圖的起始坐標(biāo)設(shè)置為檀香山的一個點。

在告訴地圖要顯示的內(nèi)容時,給出緯度和經(jīng)度足以使地圖居中,但您還必須指定要顯示的矩形區(qū)域,以獲得正確的縮放級別。

將以下常量和輔助方法添加到類中:

let regionRadius: CLLocationDistance = 1000
func centerMapOnLocation(location: CLLocation) {
  let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate, 
    regionRadius, regionRadius)
  mapView.setRegion(coordinateRegion, animated: true)
}

location參數(shù)是中心點。 該區(qū)域?qū)⒏鶕?jù)區(qū)域的距離而具有南北和東西跨度。 您將其設(shè)置為1000米:稍微超過半英里,這適用于在JSON文件中繪制藝術(shù)品數(shù)據(jù)。

setRegion(_:animated :)告訴mapView顯示該區(qū)域。 地圖視圖使用簡潔的縮放動畫自動將當(dāng)前視圖轉(zhuǎn)換到所需區(qū)域,無需額外代碼!

回到viewDidLoad(),將以下行添加到方法的末尾:

centerMapOnLocation(location: initialLocation)

您正在調(diào)用輔助方法以在啟動時放大initialLocation。

Build并運行應(yīng)用程序,您將發(fā)現(xiàn)自己位于Waikiki(地名)的中心。


Obtaining Public Artworks Data - 獲取公共藝術(shù)品數(shù)據(jù)

下一步是在當(dāng)前位置周圍繪制有趣的數(shù)據(jù)。但是在哪里可以得到這樣的東西?

那么,這取決于你當(dāng)前的位置。與許多城市一??樣,檀香山有一個 Open Data Portal,可以改善公眾對政府?dāng)?shù)據(jù)的訪問。與許多城市一??樣,檀香山的數(shù)據(jù)門戶是Socrata提供支持的,這是一個開放的數(shù)據(jù)框架,提供了一組豐富的developer tools,用于訪問基于Socrata的數(shù)據(jù)。完成本教程后,可以查看附近的城市是否有可以使用的備用數(shù)據(jù)集?

在本教程中,您將使用Honolulu Public Art。為了簡單起見,我已經(jīng)從門戶網(wǎng)站下載了這些數(shù)據(jù),并將其包含在項目中。

要了解此數(shù)據(jù)集中的項目,請在Xcode編輯器中打開PublicArt.json,然后向下滾動到第1180行(或使用?+ L表示跳轉(zhuǎn)到行),以“data”開頭,后跟數(shù)組數(shù)組 - 每個藝術(shù)品一個數(shù)組。對于本教程,您將僅使用每個數(shù)組中的一些屬性:藝術(shù)作品的location name, discipline, title, latitude and longitude。例如,對于第一個數(shù)據(jù)項:

  • location name - 地點名稱Lester McCoy Pavilion
  • disciplineMural
  • title - 標(biāo)題The Makahiki Festival – The Makai Mural
  • latitude - 緯度21.290824
  • longitude - 經(jīng)度-157.85131

在本教程的后面,您將解析此數(shù)據(jù)集以創(chuàng)建一藝術(shù)作品數(shù)組,但首先,要直接跳轉(zhuǎn)到MapKit,您只需在地圖上繪制其中一件作品。


Showing an Artwork on the Map - 在地圖上顯示藝術(shù)品

PublicArt.json中,跳轉(zhuǎn)或滾動到第1233行的項目55:它是威基基蓋特威公園的大衛(wèi)卡拉卡瓦國王的青銅雕像。

Photo of King David Kalakaua statue, by Wally Gobetz

該項目的屬性是:

  • location name - 地點名稱:威基基蓋特威公園
  • discipline:雕塑
  • title - 標(biāo)題:大衛(wèi)卡拉卡瓦國王
  • latitude - 緯度21.283921
  • longitude - 經(jīng)度-157.831661

要在地圖視圖上顯示此內(nèi)容,您必須創(chuàng)建map annotation。 map annotation是綁定到特定位置的小塊信息,并且通常在Apple的Maps應(yīng)用中表示為pins。

要創(chuàng)建自己的annotations,可以創(chuàng)建符合MKAnnotation協(xié)議的類,將annotations添加到地圖,并通知地圖應(yīng)如何顯示annotations

1. The Artwork Class - Artwork類

首先,在新的Swift文件中創(chuàng)建一個Artwork類:File \ New \ File,選擇iOS \ Source \ Swift File,然后單擊Next。 將Save As設(shè)置為Artwork.swift,然后單擊Create。

在編輯器中打開Artwork.swift并在import Foundation下面添加以下內(nèi)容:

import MapKit

class Artwork: NSObject, MKAnnotation {
  let title: String?
  let locationName: String
  let discipline: String
  let coordinate: CLLocationCoordinate2D
  
  init(title: String, locationName: String, discipline: String, coordinate: CLLocationCoordinate2D) {
    self.title = title
    self.locationName = locationName
    self.discipline = discipline
    self.coordinate = coordinate
    
    super.init()
  }
  
  var subtitle: String? {
    return locationName
  }
}

要采用MKAnnotation協(xié)議,Artwork必須是NSObject的子類,因為MKAnnotation是一個NSObjectProtocol

MKAnnotation協(xié)議需要coordinate屬性。 如果您希望annotation view在用戶點擊pin時顯示標(biāo)題和副標(biāo)題,則您的類還需要名為titlesubtitle的屬性。

對于Artwork類來說,存儲名為titlecoordinate的屬性是完全明智的,但是沒有一個PublicArt.json屬性自然地映射到subtitle的概念。 要符合MKAnnotation協(xié)議,您可以使subtitle成為返回locationName的計算屬性。

好的,所以title, locationNamecoordinate屬性將用于MKAnnotation對象,但是discipline屬性用來做什么?你會在本教程的后面找到!

2. Adding an Annotation - 添加注釋

接下來,您將為地圖視圖添加一個Artwork對象,用于您要繪制的每件藝術(shù)品。 目前,您只添加了一個藝術(shù)作品,因此切換到ViewController.swift并將以下行添加到viewDidLoad()的末尾:

// show artwork on map
let artwork = Artwork(title: "King David Kalakaua",
  locationName: "Waikiki Gateway Park", 
  discipline: "Sculpture",
  coordinate: CLLocationCoordinate2D(latitude: 21.283921, longitude: -157.831661))
mapView.addAnnotation(artwork)

在這里,您將創(chuàng)建一個新的Artwork對象,并將其作為annotation添加到地圖視圖中。 MKMapView類還有一個addAnnotations :(復(fù)數(shù))方法,當(dāng)你有一個annotation數(shù)組要添加到地圖視圖時,你將在本教程的后面使用它。

Build并運行你的項目,現(xiàn)在你應(yīng)該看到King David Kalakaua的雕像在Waikiki的入口處!

默認(rèn)annotation標(biāo)記視圖顯示位置,標(biāo)記下方是標(biāo)題。 選擇標(biāo)記:它會變大,現(xiàn)在也會顯示副標(biāo)題:

嗯,沒關(guān)系,但是當(dāng)用戶點擊標(biāo)記時,你習(xí)慣于顯示標(biāo)注的pins - 一個小氣泡。 為此,您必須配置annotation視圖,這是下一步。

3. Configuring the Annotation View - 配置注釋視圖

配置annotation視圖的一種方法是實現(xiàn)地圖視圖的mapView(_:viewFor :)代理方法。 您在此委托方法中的工作是返回MKAnnotationView的實例,以作為annotation的可視指示器呈現(xiàn)。

在這種情況下,ViewController將成為地圖視圖的代理。 為了避免混亂并提高可讀性,您將創(chuàng)建ViewController類的擴展。

ViewController.swift的底部添加以下內(nèi)容:

extension ViewController: MKMapViewDelegate {
  // 1
  func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    // 2
    guard let annotation = annotation as? Artwork else { return nil }
    // 3
    let identifier = "marker"
    var view: MKMarkerAnnotationView
    // 4
    if let dequeuedView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
      as? MKMarkerAnnotationView { 
      dequeuedView.annotation = annotation
      view = dequeuedView
    } else {
      // 5
      view = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: identifier)
      view.canShowCallout = true
      view.calloutOffset = CGPoint(x: -5, y: 5)
      view.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
    }
    return view
  }
}

這是你在做的事情:

  • 1) mapView(_:viewFor :)會為您添加到地圖的每個annotation調(diào)用(就像使用表視圖時的tableView(_:cellForRowAt :)一樣),以返回每個annotation的視圖。
  • 2) 您的應(yīng)用可能會使用其他annotation,例如用戶位置,因此請檢查此annotation是否為Artwork對象。 如果不是,則返回nil以使地圖視圖使用其默認(rèn)annotation視圖。
  • 3) 要顯示標(biāo)記,可以將每個視圖創(chuàng)建為MKMarkerAnnotationView。 在本教程的后面,您將創(chuàng)建MKAnnotationView對象,以顯示圖像而不是標(biāo)記。
  • 4) 與tableView(_:cellForRowAt :)類似,地圖視圖也會重用不再可見的annotation視圖。 因此,在創(chuàng)建新的annotation視圖之前,請檢查是否可以使用可重用的annotation視圖。
  • 5) 如果annotation視圖無法重用出列,則在此處創(chuàng)建新的MKMarkerAnnotationView對象。 它使用Artwork類的標(biāo)題和副標(biāo)題屬性來確定要在標(biāo)注中顯示的內(nèi)容。

注意:有一點需要注意的事情,由Kalgar建議,當(dāng)你將可重復(fù)使用的annotation出列時,你給它一個標(biāo)識符。 如果您有多種annotation樣式,請確保每個annotation都有唯一的標(biāo)識符,否則您可能會錯誤地將其他類型的標(biāo)識符出列,并在您的應(yīng)用中出現(xiàn)意外行為。 同樣,它與tableView(_:cellForRowAt :)中的單元標(biāo)識符背后的想法相同。

剩下的就是將ViewController設(shè)置為地圖視圖的代理。 您可以在Main.storyboard中執(zhí)行此操作,但我更喜歡在代碼中執(zhí)行此操作,它更加明顯。 在ViewController.swift中,在創(chuàng)建artwork的語句之前,將此行添加到viewDidLoad()

mapView.delegate = self

就是這樣! Build并運行項目,然后點擊標(biāo)記以彈出標(biāo)注氣泡:

mapView(_:viewFor :)將標(biāo)注配置為在右側(cè)包含詳細(xì)信息披露信息按鈕,但點擊該按鈕尚未執(zhí)行任何操作。 您可以實現(xiàn)它以顯示包含更多信息的alert彈窗,或者打開詳細(xì)視圖控制器。

這是一個很好的第三個選項:當(dāng)用戶點擊信息按鈕時,您的應(yīng)用程序?qū)?code>Maps應(yīng)用程序,完成駕駛/步行/公交路線,從模擬用戶位置到藝術(shù)品!


Launching the Maps App - 啟動Maps應(yīng)用程序

要提供這種出色的用戶體驗,請打開Artwork.swift并在其他兩個下面添加此import語句:

import Contacts

這將添加Contacts框架,其中包含字典鍵常量,例如CNPostalAddressStreetKey,用于需要設(shè)置位置的地址,城市或州字段。

接下來,將以下輔助方法添加到類中:

// Annotation right callout accessory opens this mapItem in Maps app
func mapItem() -> MKMapItem {
  let addressDict = [CNPostalAddressStreetKey: subtitle!]
  let placemark = MKPlacemark(coordinate: coordinate, addressDictionary: addressDict)
  let mapItem = MKMapItem(placemark: placemark)
  mapItem.name = title
  return mapItem
}

在這里,您可以從MKPlacemark創(chuàng)建MKMapItem。 地圖應(yīng)用程序能夠讀取此MKMapItem,并顯示正確的內(nèi)容。

接下來,您必須告訴MapKit當(dāng)用戶點擊callout按鈕時該怎么做。 打開ViewController.swift,并將此方法添加到MKMapViewDelegate擴展:

func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView,
    calloutAccessoryControlTapped control: UIControl) {
  let location = view.annotation as! Artwork
  let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving]
  location.mapItem().openInMaps(launchOptions: launchOptions)
}

當(dāng)用戶點擊地圖annotation標(biāo)記時,標(biāo)注會顯示一個信息按鈕。如果用戶點擊此信息按鈕,則調(diào)用mapView(_:annotationView:calloutAccessoryControlTapped :)方法。

在此方法中,您將獲取此點擊要引用的Artwork對象,然后通過創(chuàng)建關(guān)聯(lián)的MKMapItem并在map item上調(diào)用openInMaps(launchOptions :)來啟動Maps應(yīng)用。

請注意,您正在將字典傳遞給此方法。這允許您指定幾個不同的選項;這里DirectionModeKey設(shè)置為Driving。這會導(dǎo)致Maps應(yīng)用顯示從用戶當(dāng)前位置到此pin的行車路線。

注意:瀏覽MKMapItem documentation以查看其他啟動選項字典鍵,以及openMaps(with:launchOptions :)方法,該方法允許您傳遞MKMapItem對象數(shù)組。

在你Build和運行之前,你應(yīng)該搬到檀香山 - 實際上,只需將你的模擬位置設(shè)置為檀香山。在Xcode中,轉(zhuǎn)到Product \ Scheme \ Edit Scheme ...,從左側(cè)菜單中選擇Run,然后選擇Options選項卡。檢查Core Location: Allow Location Simulation,并選擇Honolulu, HI, USA作為Default Location。然后單擊Close按鈕:

Build并運行應(yīng)用程序,您將看到地圖放大Waikiki,就像之前一樣。 點擊標(biāo)記,然后點擊標(biāo)注中的info按鈕,并觀看它啟動Maps應(yīng)用以顯示雕像的位置,并顯示其行車路線:

注意:首次打開Maps時,系統(tǒng)會提示您允許Maps訪問您的位置(點按允許),并顯示安全警告。

后記

本篇主要講述了基本使用簡單示例,感興趣的給個贊或者關(guān)注~~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容