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

版本記錄

版本號(hào) 時(shí)間
V1.0 2018.10.14 星期日

前言

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

Parsing JSON Data into Artwork Objects - 將JSON數(shù)據(jù)解析為Artwork對(duì)象

現(xiàn)在您已了解如何在地圖上顯示一件artwork垫挨,以及如何從pin的標(biāo)注信息按鈕啟動(dòng)Maps應(yīng)用程序韩肝,現(xiàn)在是時(shí)候?qū)?shù)據(jù)集解析為一個(gè)Artwork對(duì)象數(shù)組。 然后九榔,您將它們作為annotations添加到地圖視圖中哀峻,以顯示位于當(dāng)前地圖區(qū)域中的所有藝術(shù)品涡相。

將這個(gè)可用的初始化程序添加到初始化程序下面的Artwork.swift

init?(json: [Any]) {
  // 1
  self.title = json[16] as? String ?? "No Title"
  self.locationName = json[12] as! String
  self.discipline = json[15] as! String
  // 2
  if let latitude = Double(json[18] as! String),
    let longitude = Double(json[19] as! String) {
  self.coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
  } else {
    self.coordinate = CLLocationCoordinate2D()
  }
}

這是你正在做的事情:

  • 1) json參數(shù)是表示藝術(shù)作品的數(shù)組之一 - Any對(duì)象的數(shù)組。 如果計(jì)算數(shù)組的元素剩蟀,您將看到title催蝗,locationName等位于此方法中指定的索引處。 某些artworkstitle字段為null育特,因此您為title值提供默認(rèn)值丙号。
  • 2) json數(shù)組中的緯度和經(jīng)度值是字符串:如果可以從它們創(chuàng)建Double對(duì)象,則創(chuàng)建CLLocationCoordinate2D且预。

換句話(huà)說(shuō)槽袄,這個(gè)初始化器轉(zhuǎn)換一個(gè)這樣的數(shù)組:

[ 55, "8492E480-43E9-4683-927F-0E82F3E1A024", 55, 1340413921, "436621", 1340413921, "436621", "{\n}", "Sean Browne", "Gift of the Oahu Kanyaku Imin Centennial Committee", "1989", "Large than life-size bronze figure of King David Kalakaua mounted on a granite pedestal. Located at Waikiki Gateway Park.", "Waikiki Gateway Park", "http://hiculturearts.pastperfect-online.com/34250images/002/199103-3.JPG", "1991.03", "Sculpture", "King David Kalakaua", "Full", "21.283921", "-157.831661", [ null, "21.283921", "-157.831661", null, false ], null ]

進(jìn)入您之前創(chuàng)建的Artwork對(duì)象:

  • locationName: “Waikiki Gateway Park”
  • discipline: “Sculpture”
  • title: “King David Kalakaua”
  • coordinate with latitude: 21.283921 longitude: -157.831661

要使用此初始化程序,請(qǐng)打開(kāi)ViewController.swift锋谐,并將以下屬性添加到類(lèi)中 - 一個(gè)用于保存JSON文件中的Artwork對(duì)象的數(shù)組:

var artworks: [Artwork] = []

接下來(lái)遍尺,將以下輔助方法添加到類(lèi)中:

func loadInitialData() {
  // 1
  guard let fileName = Bundle.main.path(forResource: "PublicArt", ofType: "json") 
    else { return }
  let optionalData = try? Data(contentsOf: URL(fileURLWithPath: fileName))

  guard
    let data = optionalData,
    // 2
    let json = try? JSONSerialization.jsonObject(with: data),
    // 3
    let dictionary = json as? [String: Any],
    // 4
    let works = dictionary["data"] as? [[Any]]
    else { return }
  // 5
  let validWorks = works.flatMap { Artwork(json: $0) }
  artworks.append(contentsOf: validWorks)
}

以下是您在此代碼中所做的事情:

  • 1) 您將PublicArt.json文件讀入Data對(duì)象。
  • 2) 您使用JSONSerialization來(lái)獲取JSON對(duì)象涮拗。
  • 3) 您檢查JSON對(duì)象是具有String鍵和Any值的字典乾戏。
  • 4) 您只對(duì)其鍵為data的JSON對(duì)象感興趣。
  • 5) 您使用剛剛添加到Artwork類(lèi)的可用初始化程序?qū)@個(gè)數(shù)組進(jìn)行flatmap三热,并將生成的validWorks附加到artwork數(shù)組中鼓择。

Plotting the Artworks - 繪制Artworks

您現(xiàn)在擁有數(shù)據(jù)集中所有公共藝術(shù)作品的數(shù)組,您將添加到地圖中就漾。

仍然在ViewController.swift中呐能,在viewDidLoad()的末尾添加以下代碼:

loadInitialData()
mapView.addAnnotations(artworks)

注意:請(qǐng)務(wù)必使用復(fù)數(shù)addAnnotations,而不是單數(shù)addAnnotation

注釋或刪除創(chuàng)建單個(gè)“King David Kalakaua”地圖annotation的行 - 您現(xiàn)在不需要它們象踊,現(xiàn)在loadInitialData創(chuàng)建artworks數(shù)組:

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

Build并運(yùn)行您的應(yīng)用程序并檢查所有標(biāo)記!

移動(dòng)地圖以查看其他標(biāo)記魄幕。 例如,在您的初始位置的北面量愧,在1號(hào)高速公路上方,是Honolulu’s Pioneer Artesian Well

注意:標(biāo)記的西北部是Punahou學(xué)校暖哨,它聲稱(chēng)一位前美國(guó)總統(tǒng)作為校友赌朋! 西部的標(biāo)記是他出生的醫(yī)院。

點(diǎn)擊一個(gè)標(biāo)記打開(kāi)其callout氣泡篇裁,然后點(diǎn)擊其信息按鈕啟動(dòng)Maps應(yīng)用程序 - 是的沛慢,您使用King Kalakaua雕像所做的一切都適用于所有這些新作品!

注意:感謝Dave Mark指出 Apple recommends adding all the annotations right away达布,無(wú)論它們是否在地圖區(qū)域中可見(jiàn) - 當(dāng)您移動(dòng)地圖時(shí)团甲,它會(huì)自動(dòng)顯示可見(jiàn)annotations

就是這樣黍聂! 您已經(jīng)構(gòu)建了一個(gè)應(yīng)用程序躺苦,將JSON文件解析為一artworks數(shù)組身腻,然后將其顯示為注釋標(biāo)記(annotation markers),并帶有一個(gè)用于啟動(dòng)Maps應(yīng)用程序的callout info按鈕匹厘!


Customizing Annotations - 自定義注釋

1. Markers with Color-Coding & Text - 帶有顏色編碼和文本的標(biāo)記

還記得Artwork類(lèi)中的discipline屬性嗎嘀趟? 它的價(jià)值觀(guān)就像“Sculpture”“Mural” - 實(shí)際上,最多的disciplines是雕塑愈诚,牌匾她按,壁畫(huà)和紀(jì)念碑。 對(duì)標(biāo)記進(jìn)行顏色編碼很容易炕柔,因此這些disciplines具有不同顏色的標(biāo)記酌泰,所有其他disciplines都有綠色標(biāo)記。

Artwork.swift中匕累,添加以下屬性:

// markerTintColor for disciplines: Sculpture, Plaque, Mural, Monument, other
var markerTintColor: UIColor  {
  switch discipline {
  case "Monument":
    return .red
  case "Mural":
    return .cyan
  case "Plaque":
    return .blue
  case "Sculpture":
    return .purple
  default:
    return .green
  }
}

現(xiàn)在陵刹,您可以繼續(xù)向mapView(_:viewFor :)添加代碼,但這會(huì)使視圖控制器變得混亂哩罪。 有一種更優(yōu)雅的方式授霸,類(lèi)似于您可以為表視圖單元格執(zhí)行的操作。 創(chuàng)建一個(gè)名為ArtworkViews.swift的新Swift文件际插,并在import語(yǔ)句下面添加此代碼:

import MapKit

class ArtworkMarkerView: MKMarkerAnnotationView {
  override var annotation: MKAnnotation? {
    willSet {
      // 1
      guard let artwork = newValue as? Artwork else { return }
      canShowCallout = true
      calloutOffset = CGPoint(x: -5, y: 5)
      rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
      // 2
      markerTintColor = artwork.markerTintColor
      glyphText = String(artwork.discipline.first!)
    }
  }
}

很快碘耳,您將此類(lèi)注冊(cè)為Artwork annotations的可重用annotation視圖。 系統(tǒng)會(huì)將注釋作為newValue傳遞給你框弛,所以這就是你正在做的事情:

  • 1) 這些行與mapView(_:viewFor :)完成相同的操作辛辨,配置callout
  • 2) 然后設(shè)置標(biāo)記的色調(diào)顏色瑟枫,并將其pin icon(glyph)替換為annotation’s discipline的第一個(gè)字母斗搞。

現(xiàn)在切換到ViewController.swift,并在調(diào)用loadInitialData()之前將此行添加到viewDidLoad()

mapView.register(ArtworkMarkerView.self, 
  forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)

在這里慷妙,您使用地圖視圖的默認(rèn)重用標(biāo)識(shí)符注冊(cè)新類(lèi)僻焚。 對(duì)于具有更多annotation類(lèi)型的應(yīng)用程序,您將使用自定義標(biāo)識(shí)符注冊(cè)類(lèi)膝擂。

向下滾動(dòng)到擴(kuò)展虑啤,并注釋掉mapView(_:viewFor :)方法。

Build并運(yùn)行您的應(yīng)用程序架馋,然后移動(dòng)地圖狞山,以查看不同顏色和標(biāo)記的標(biāo)記:

在地圖的這一部分中,實(shí)際上有比地圖視圖更多的artworks:它通過(guò)聚類(lèi)太靠近的標(biāo)記來(lái)減少混亂叉寂。 在下一節(jié)中萍启,您將看到所有annotations

但首先,設(shè)置字形的圖像而不是文本勘纯。 將以下屬性添加到Artwork.swift

var imageName: String? {
  if discipline == "Sculpture" { return "Statue" }
  return "Flag"
}

來(lái)自icons8.com的這些圖片已經(jīng)在Images.xcassets中局服。

Build并運(yùn)行您的應(yīng)用程序以查看帶有圖像的不同顏色標(biāo)記:

這是另一個(gè)自定義選項(xiàng),你的下一個(gè)任務(wù):用圖像替換標(biāo)記屡律!

2. Images, Not Markers - 圖像腌逢,而不是標(biāo)記

ArtworkViews.swift中,添加以下類(lèi):

class ArtworkView: MKAnnotationView {
  override var annotation: MKAnnotation? {
    willSet {
      guard let artwork = newValue as? Artwork else {return}
      canShowCallout = true
      calloutOffset = CGPoint(x: -5, y: 5)
      rightCalloutAccessoryView = UIButton(type: .detailDisclosure)

      if let imageName = artwork.imageName {
        image = UIImage(named: imageName)
      } else {
        image = nil
      }
    }
  }
}

現(xiàn)在超埋,您使用的是普通的舊MKAnnotationView而不是MKMarkerAnnotationView搏讶,并且視圖具有image屬性。

回到ViewController.swift霍殴,在viewDidLoad()中媒惕,注冊(cè)這個(gè)新類(lèi),而不是ArtworkMarkerView

mapView.register(ArtworkView.self, 
  forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)

Build并運(yùn)行您的應(yīng)用程序以查看雕塑和標(biāo)志:

現(xiàn)在来庭,您沒(méi)有看到標(biāo)題妒蔚,但地圖視圖顯示了所有annotations

3. Custom Callout Accessory Views - 自定義標(biāo)注附件視圖

正確的標(biāo)注附件是一個(gè)信息按鈕月弛,但點(diǎn)擊它會(huì)打開(kāi)Maps應(yīng)用肴盏,所以現(xiàn)在您將更改按鈕以顯示地圖圖標(biāo)。

ArtworkView中找到這一行:

rightCalloutAccessoryView = UIButton(type: .detailDisclosure)

用下面代碼替換上面那一行

let mapsButton = UIButton(frame: CGRect(origin: CGPoint.zero,
   size: CGSize(width: 30, height: 30)))
mapsButton.setBackgroundImage(UIImage(named: "Maps-icon"), for: UIControlState())
rightCalloutAccessoryView = mapsButton

在這里帽衙,您創(chuàng)建一個(gè)UIButton菜皂,將其背景圖像設(shè)置為Images.xcassetsiconarchive.com的Maps圖標(biāo),然后將視圖右側(cè)標(biāo)注附件設(shè)置為此按鈕厉萝。

Build并運(yùn)行您的應(yīng)用恍飘,然后點(diǎn)按視圖以查看新的地圖按鈕:

最后的定制是細(xì)節(jié)標(biāo)注附件(detail callout accessory):它是一行,足以用于短位置文本谴垫,但是如果你想要顯示大量文本呢章母?

Artwork.swift中,在init(json :)中找到這一行:

self.locationName = json[12] as! String

用下面這行進(jìn)行替換

self.locationName = json[11] as! String

在這里翩剪,您選擇了artwork的長(zhǎng)描述乳怎,這不適用于默認(rèn)的單行細(xì)節(jié)標(biāo)注附件。 現(xiàn)在您需要一個(gè)多行標(biāo)簽:將以下代碼添加到ArtworkView

let detailLabel = UILabel()
detailLabel.numberOfLines = 0
detailLabel.font = detailLabel.font.withSize(12)
detailLabel.text = artwork.subtitle
detailCalloutAccessoryView = detailLabel

Build并運(yùn)行您的應(yīng)用前弯,然后點(diǎn)按視圖以查看詳細(xì)說(shuō)明:


Bonus Topic: User Location Authorization - 獎(jiǎng)金主題:用戶(hù)位置授權(quán)

此應(yīng)用程序無(wú)需要求用戶(hù)授權(quán)訪(fǎng)問(wèn)其位置舞肆,但您可能希望將其包含在其他基于MapKit的應(yīng)用程序中。

ViewController.swift中博杖,添加以下行:

let locationManager = CLLocationManager()
func checkLocationAuthorizationStatus() {
  if CLLocationManager.authorizationStatus() == .authorizedWhenInUse {
    mapView.showsUserLocation = true
  } else {
    locationManager.requestWhenInUseAuthorization()
  }
}

override func viewDidAppear(_ animated: Bool) {
  super.viewDidAppear(animated)
  checkLocationAuthorizationStatus()
}

在這里,您可以創(chuàng)建一個(gè)CLLocationManager來(lái)跟蹤應(yīng)用程序的授權(quán)狀態(tài)筷登,以便訪(fǎng)問(wèn)用戶(hù)的位置剃根。 在checkLocationAuthorizationStatus()中,如果您的應(yīng)用已獲得授權(quán)前方,則tick地圖視圖的Shows-User-Location復(fù)選框狈醉;否則廉油,您告訴locationManager請(qǐng)求用戶(hù)授權(quán)。

注意:locationManager可以發(fā)出兩種授權(quán)請(qǐng)求:requestWhenInUseAuthorizationrequestAlwaysAuthorization苗傅。第一個(gè)讓你的應(yīng)用程序在前臺(tái)使用位置服務(wù)抒线;第二個(gè)授權(quán)您的應(yīng)用程序運(yùn)行時(shí)。 Apple’s documentation不鼓勵(lì)使用“Always”
由于對(duì)用戶(hù)隱私的潛在負(fù)面影響渣慕,不鼓勵(lì)請(qǐng)求“Always”授權(quán)嘶炭。只有這樣做才能為用戶(hù)提供真正的好處,您才應(yīng)該請(qǐng)求此級(jí)別的授權(quán)逊桦。

1. Info.plist item: important but easy to overlook! - Info.plist項(xiàng)目:重要但容易被忽視眨猎!

您還需要執(zhí)行一項(xiàng)與授權(quán)相關(guān)的任務(wù) - 如果不這樣做,您的應(yīng)用程序不會(huì)崩潰强经,但不會(huì)出現(xiàn)locationManager的請(qǐng)求睡陪。要使請(qǐng)求生效,您必須提供一條消息匿情,向用戶(hù)解釋您的應(yīng)用想要訪(fǎng)問(wèn)其位置的原因兰迫。

Info.plist中,打開(kāi)Information Property List炬称。將光標(biāo)懸停在上下箭頭上汁果,或單擊列表中的任何項(xiàng)目,以顯示+和 - 符號(hào)转砖,然后單擊+符號(hào)以創(chuàng)建新項(xiàng)目须鼎。向下滾動(dòng)以選擇Privacy – Location When In Use Usage Description,然后將其值設(shè)置為類(lèi)似To show you cool things nearby:

Build并運(yùn)行府蔗。 您會(huì)在啟動(dòng)時(shí)看到權(quán)限請(qǐng)求:

有這樣的用法說(shuō)明晋控,誰(shuí)不允許訪(fǎng)問(wèn)?

注意:從iOS 11開(kāi)始姓赤,如果不提供“When in Use”赡译,則無(wú)法請(qǐng)求“Always”:如果您僅設(shè)置Privacy – Location Always Usage Description,則不會(huì)顯示不铆,并且您將收到錯(cuò)誤消息“Info.plist must contain both NSLocationAlwaysAndWhenInUseUsageDescription and NSLocationWhenInUseUsageDescription keys…”蝌焚。

下面,location manager要求“Always”

現(xiàn)在您已經(jīng)了解了使用MapKit的基礎(chǔ)知識(shí)誓斥,但您可以添加更多內(nèi)容:地理編碼只洒,地理圍欄,自定義地圖疊加等劳坑。 Apple的Location and Maps Programming Guide是查找其他信息的好地方毕谴。

另請(qǐng)參閱WWDC 2017 Session 237 MapKit中的新功能,以查找他們?cè)趇OS 11中添加的更多酷炫功能。


源碼

首先我們看一下工程文件

接著看一下sb中的內(nèi)容

接著我們就看一下源碼

1. Swift源碼

1. ViewController.swift
import UIKit
import MapKit

class ViewController: UIViewController {

  // MARK: - Properties
  var artworks: [Artwork] = []
  @IBOutlet weak var mapView: MKMapView!
  let regionRadius: CLLocationDistance = 1000

  // MARK: - View life cycle

  override func viewDidLoad() {
    super.viewDidLoad()
    // set initial location in Honolulu
    let initialLocation = CLLocation(latitude: 21.282778, longitude: -157.829444)
    centerMapOnLocation(location: initialLocation)

    mapView.delegate = self
//    mapView.register(ArtworkMarkerView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)
    mapView.register(ArtworkView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)
    loadInitialData()
    mapView.addAnnotations(artworks)

    // 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)
  }

  override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    checkLocationAuthorizationStatus()
  }

  // MARK: - CLLocationManager

  let locationManager = CLLocationManager()
  func checkLocationAuthorizationStatus() {
    if CLLocationManager.authorizationStatus() == .authorizedAlways {
      mapView.showsUserLocation = true
    } else {
      locationManager.requestAlwaysAuthorization()
    }
//    if CLLocationManager.authorizationStatus() == .authorizedWhenInUse {
//      mapView.showsUserLocation = true
//    } else {
//      locationManager.requestWhenInUseAuthorization()
//    }
  }

  // MARK: - Helper methods

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

  func loadInitialData() {
    // 1
    guard let fileName = Bundle.main.path(forResource: "PublicArt", ofType: "json")
      else { return }
    let optionalData = try? Data(contentsOf: URL(fileURLWithPath: fileName))

    guard
      let data = optionalData,
      // 2
      let json = try? JSONSerialization.jsonObject(with: data),
      // 3
      let dictionary = json as? [String: Any],
      // 4
      let works = dictionary["data"] as? [[Any]]
      else { return }
    // 5
    let validWorks = works.flatMap { Artwork(json: $0) }
    artworks.append(contentsOf: validWorks)
  }

}

// MARK: - MKMapViewDelegate

extension ViewController: MKMapViewDelegate {

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

  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)
  }

}
2. Artwork.swift
import Foundation
import MapKit
import Contacts

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()
  }

  init?(json: [Any]) {
    // 1
    if let title = json[16] as? String {
      self.title = title
    } else {
      self.title = "No Title"
    }
    // json[11] is the long description
    self.locationName = json[11] as! String
    // json[12] is the short location string
//    self.locationName = json[12] as! String
    self.discipline = json[15] as! String
    // 2
    if let latitude = Double(json[18] as! String),
      let longitude = Double(json[19] as! String) {
      self.coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
    } else {
      self.coordinate = CLLocationCoordinate2D()
    }
  }

  var subtitle: String? {
    return locationName
  }

  // pinTintColor for disciplines: Sculpture, Plaque, Mural, Monument, other
  var markerTintColor: UIColor  {
    switch discipline {
    case "Monument":
      return .red
    case "Mural":
      return .cyan
    case "Plaque":
      return .blue
    case "Sculpture":
      return .purple
    default:
      return .green
    }
  }

  var imageName: String? {
    if discipline == "Sculpture" { return "Statue" }
    return "Flag"
  }

  // 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
  }

}
3. ArtworkViews.swift
import Foundation
import MapKit

class ArtworkMarkerView: MKMarkerAnnotationView {

  override var annotation: MKAnnotation? {
    willSet {
      guard let artwork = newValue as? Artwork else { return }
      canShowCallout = true
      calloutOffset = CGPoint(x: -5, y: 5)
      rightCalloutAccessoryView = UIButton(type: .detailDisclosure)

      markerTintColor = artwork.markerTintColor
//      glyphText = String(artwork.discipline.first!)
        if let imageName = artwork.imageName {
          glyphImage = UIImage(named: imageName)
        } else {
          glyphImage = nil
      }
    }
  }

}

class ArtworkView: MKAnnotationView {

  override var annotation: MKAnnotation? {
    willSet {
      guard let artwork = newValue as? Artwork else {return}

      canShowCallout = true
      calloutOffset = CGPoint(x: -5, y: 5)
      let mapsButton = UIButton(frame: CGRect(origin: CGPoint.zero,
        size: CGSize(width: 30, height: 30)))
      mapsButton.setBackgroundImage(UIImage(named: "Maps-icon"), for: UIControlState())
      rightCalloutAccessoryView = mapsButton
//      rightCalloutAccessoryView = UIButton(type: .detailDisclosure)

      if let imageName = artwork.imageName {
        image = UIImage(named: imageName)
      } else {
        image = nil
      }

      let detailLabel = UILabel()
      detailLabel.numberOfLines = 0
      detailLabel.font = detailLabel.font.withSize(12)
      detailLabel.text = artwork.subtitle
      detailCalloutAccessoryView = detailLabel
    }
  }

}

下面看一下點(diǎn)擊info按鈕打開(kāi)Maps應(yīng)用的效果涝开。

后記

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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市舀武,隨后出現(xiàn)的幾起案子拄养,更是在濱河造成了極大的恐慌,老刑警劉巖银舱,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瘪匿,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡纵朋,警方通過(guò)查閱死者的電腦和手機(jī)柿顶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)操软,“玉大人嘁锯,你說(shuō)我怎么就攤上這事∧粜剑” “怎么了家乘?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)藏澳。 經(jīng)常有香客問(wèn)我仁锯,道長(zhǎng),這世上最難降的妖魔是什么翔悠? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任业崖,我火速辦了婚禮,結(jié)果婚禮上蓄愁,老公的妹妹穿的比我還像新娘双炕。我一直安慰自己,他們只是感情好撮抓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布妇斤。 她就那樣靜靜地躺著,像睡著了一般丹拯。 火紅的嫁衣襯著肌膚如雪站超。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天乖酬,我揣著相機(jī)與錄音死相,去河邊找鬼。 笑死咬像,一個(gè)胖子當(dāng)著我的面吹牛媳纬,可吹牛的內(nèi)容都是我干的双肤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼钮惠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了七芭?” 一聲冷哼從身側(cè)響起素挽,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎狸驳,沒(méi)想到半個(gè)月后预明,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡耙箍,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年撰糠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辩昆。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡阅酪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出汁针,到底是詐尸還是另有隱情术辐,我是刑警寧澤验毡,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布邦危,位于F島的核電站沾乘,受9級(jí)特大地震影響嚎花,放射性物質(zhì)發(fā)生泄漏椰苟。R本人自食惡果不足惜萨蚕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一印屁、第九天 我趴在偏房一處隱蔽的房頂上張望莺禁。 院中可真熱鬧兴想,春花似錦幢哨、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至顽悼,卻和暖如春曼振,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蔚龙。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工冰评, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人木羹。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓甲雅,卻偏偏與公主長(zhǎng)得像解孙,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子抛人,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

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