本文由 CocoaChina 譯者 ztdj121 翻譯
原文:MapKit for iOS 9: Flyover, Transit and Customization
原文作者:Eva Diaz-Santana
在2015年的WWDC(蘋果全球開發者論壇)中,蘋果推出了最新一代操作系統iOS 9。iOS 9系統主要在iOS 8系統的基礎上進行了優化,並添加了一些新功能。對於開發者而言,其中值得關注的一項就是MapKit的更新。很長時間以來人們一直在開發論壇裡要求添加新特性,現在終於如願以償。讓我們詳細看看這些新特性。
自定義大頭針顏色自推出iOS3以來,在MapKit中,大頭針(MKPinAnnotationView的一個實例)可用的顏色非常有限。基本上,可選的大頭針顏色只有紅色、綠色和紫色。在iOS 9中,現在我們可以自定義大頭針的顏色。UIColor類的一個新屬性pinTintColor允許你給大頭針賦予任何顏色的值。先前的pinColor屬性已經棄用了。
自定義標注
標注是點擊注釋視圖彈出的視圖。默認情況下,它有四個部分:標題、副標題、右輔助視圖和左輔助視圖。這些標注組件對非常有限的定制來說是足夠了。如果你需要更多的,可以使用UIView類的新屬性detailCalloutAccessoryView。這個屬性允許你給標注添加任何視圖。你可能使用到新的UIStackView。如果你想了解更多關於UIStackView,可以查看這個教程:UIStackView, Auto Layout and Core Animation。作為UIView的新屬性,detailCalloutAccessoryView支持自動布局、從左到右的語言,以及使用UIView能做的任何操作。
想要創建一個自定義的標注,你只要將canShowCallout的屬性設置為ture,這樣標注就可見了,然後把你想要的任何UIView傳給detailCalloutAccessoryView。可參看這個例子:
view.canShowCallout = true view.detailCalloutAccessoryView = UIImage(image:UIImage(named:"YourImageName"))
自定義地圖
通過自定義地圖,我們可以控制我們想要在地圖視圖上所呈現的東西。通過showsTraffic, showsScale 以及showsCompass這三個屬性為開發者提供新的可能性。這三個屬性是布爾值。把它們設為true,將在地圖上顯示交通、比例和指南針。
時區支持
時區支持是獲得相關時區的屬性。它可以和CLGeocoder聯合使用來找到與特定坐標相關的時區,或者和MKLocalSearch一起使用來查詢某個點相關的時區。
交通
MapKit 允許交通ETA(預計到達時間)請求。直到現在,只有三種類型的交通提供給了開發者:Automobile(汽車)、Walking(步行)和Any(任何)。但iOS 9介紹了一個新的類型:Transit(交通),所以在iOS 9中 MKDirectionsTransportType是這樣的:
struct MKDirectionsTransportType: OptionSetType { init(rawValue rawValue:UInt) static var Automobile: MKDirectionsTransportType { get } static var Walking: MKDirectionsTransportType { get } static var Transit: MKDirectionsTransportType { get } static var Any: MKDirectionsTransportType { get } }
除了ETA,你還可以得到預期的到達和離開的時間。現在,我們來看看怎樣請求一個交通ETA:
func getTransitETA() { let request = MKDirectionRequest() // 3 let source = MKMapItem(placemark: MKPlacemark(coordinate:CLLocationCoordinate2D(latitude: 37.78257, longitude: -122.41115), addressDictionary: nil)) // 4 source.name = "iNVASIVECODE HQ" request.source = source //5 let destination = MKMapItem(placemark: MKPlacemark(coordinate:CLLocationCoordinate2D(latitude: 37.79467, longitude: -122.39302), addressDictionary: nil)) // 6 destination.name = "Ferry Building" request.destination = destination // 7 request.transportType = MKDirectionsTransportType.Transit // 8 let directions = MKDirections(request: request) // 9 directions.calculateETAWithCompletionHandler { response, error in // 10 if error == nil { if let r = response { print(r.expectedTravelTime) // 11 } } } }
在第3行,我創建了一個MKDirectionRequest。
然後,我創建了一個帶有iNVASIVECODE HQ(第4行)坐標的MKMapItem,並把它標記成路徑方向的起始點(第5行)。
對目的地也是一樣的做法:創建一個MKMapItem(第6行),把它標記成路徑方向的終點點(第7行)。然後給Transit設置transportType(交通類型)(第8行)。
最後,用第3行的request創建一個MKDirections對象(第9行),然後開始計算被請求的交通時間信息(第10行)。最後打印出以秒為單位的預計行進時間(第11行)。
收到來自蘋果服務器的應答之後,你可以在開車、步行或者啟程時從iOS 9重用交通模式啟動地圖。這有個例子,說明了如何從你的app中啟動應用程序地圖:
func openInMapsTransit(coord:CLLocationCoordinate2D) { var placemark = MKPlacemark(coordinate:coord, addressDictionary: nil) var mapItem = MKMapItem(placemark: placemark) // 12 let launchOptions = [MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeTransit] // 13 mapItem.openInMapsWithLaunchOptions(launchOptions) // 14 }
在之前的代碼片段中,我創建了一個MKMapItem(第12行)。然後,指定了打開地圖應用的啟動選項(第13行)。應該把MKLaunchOptionsDirectionsModeDriving傳給openInMapsWithLaunchOptions:方法來告訴地圖應用顯示起始和終點之間的行駛方向,或者傳遞MKLaunchOptionsDirectionsModeWalking 來告訴地圖應用顯示步行方向,或者傳遞MKLaunchOptionsDirectionsModeTransit 來告訴地圖應用顯示交通方向。在我的例子中,將傳遞MKLaunchOptionsDirectionsModeTransit 這個值。最後,打開地圖應用,並顯示地圖項目(第14行)。
支持Flyover (城市觀光)
Flyover 是一個逼真的城市和地標的3D模型。自iOS 6.0以來,地圖中一直有這個,但目前為止在MapKit框架中都是不能用的。iOS 9中,flyover也提供給開發者了。Flyover在世界上很多地方是可用的,但不是每個地方都可用。Flyover不可用的地方,將會在3D地形圖上方顯示平坦的衛星圖像(高度模型)。
MKMapView類裡的mapType屬性允許你定義通過地圖視圖顯示的數據的類型。從iOS 3開始,有3種類型可用:標准(Standard)、衛星(Satellite)和混合(Hybrid)。iOS 9帶來了兩種新的類型:SatelliteFlyover (地形和建築物的三維模型)和HybridFlyover(和在上面顯示像道路和標簽的附加元素的SatelliteFlyover一樣)
Flyover和衛星圖像被顯示在一個地球的三維幾何模型上。所以,在使用flyover的時候,當定義你想顯示的區域時,不得不考慮一些東西。
大小限制
如果定義一個非常大的地球區域,有些地方可能看不到,因為該地區的邊界在地球視圖的邊緣,曲率很高,那些區域將會被隱藏。這時你做不了任何事情,地球是圓形的,所以不可能從每個角度看到每個區域。
失真
為了看到建築物的正面,必須使用一個傾斜的地圖視角。而不是定位相機自頂向下看,你可以傾斜相機來獲得一個區域的傾斜視角。這種情況下,你實際看到的區域就不是矩形的而是梯形的。然而,用MKCoordinateRegion和MKMapRect定義的區域是一個矩形。這種情況下,定義的矩形區域將成為可視區域的封閉矩形。
為了處理這種問題,蘋果推薦用MKMapCamera來設置地圖的可視區域。你們可以查看我在2013年寫的一篇有關MapKit in iOS 的文章來了解更多有關MKMapCamera和它新的初始化程序的知識,這些在iOS 9中都是可用的:
convenience init(lookingAtCenterCoordinate centerCoordinate: CLLocationCoordinate2D, // 15 fromDistance distance:CLLocationDistance, // 16 pitch:CGFloat, // 17 heading: CLLocationDirection) // 18
在這個初始化程序中,你可以在地形上修改相機位置的經緯度(第15行)。然後,一個以米為單位的距離定義了你想把相機放在多遠的位置(第16行)。Pitch(傾斜)(第17行)指定了用"度"來測量的相機傾斜角度。0度值表示相機是垂直指向地圖的。比0度大的角表示相機是以指定度數傾斜於地平線的。最後,heading(指向)(第18行)定義了相機應當看到(以度為單位)正北方向。
一旦你創建了相機並設置了它的屬性,你可以把相機用Camera:屬性或者setCamera:animated:方法賦值給地圖視圖。
總結
iOS 9最終給MapKit帶來了一些人們長期期待的改進。我個人覺得callout(標注)的定制相當有用。同時它有一些新的特性、交通功能和flyover(城市觀光)。交通無疑是最期望的新特性,我很期待使用這個特性,並且很有信心可以看到驚人的效果。
不斷創新,快馬加鞭!
Eva
Eva Diaz-Santana (@evdiasan)是InvasiveCode的創始人之一。她自2008年開始開發iOS應用,並教授iOS開發。她還曾在蘋果做Cocoa設計師和用戶體驗設計師。