高雄公共運輸App:Part4-高雄捷運功能頁
顯示離使用者最近的站點以及在地圖加入路線
功能
- 包含紅橘兩線以及環狀輕軌三種路線供選擇
- 初始會顯示離使用者最近的站點,以及顯示路線在地圖上
- 點擊導航Button可跳出地圖顯示導航
- 下方清單顯示主要三個功能
作法
本篇會著重在1~4的分享,對5~7有興趣的可以去看Part.3
- 使用Airtable建立所有站點資訊並載入到App中
- 使用MKMapViewDelegate客製化MKAnnotationView做出不一樣的圖標
- 使用MKOverlayRenderer畫出路線
- 使用MKMapItem跳出地圖並顯示導航
- 使用CLLocationManger追蹤使用者位置
- 使用UIPickerView顯示站點清單
- 使用sorted(by:)找出距離最近的站點
Airtable API
因為高雄捷運、輕軌沒有提供完整的站點資料,所以自己用Airtable建立資料,包含:紅橘線、輕軌(種類)、站號、站名(中英文名稱)、經緯度、轉乘站,關於Airtable串接API可以參考我之前寫過的訂飲料App文章,裡面有更詳細的解釋
訂飲料App文章
API網址
sort[][field]=stationNumber這段是我希望他回傳的資料排序是以站號排序
sort[][direction]=desc這段則是希望他由大到小排序
https://api.airtable.com/v0/appq3eCZQEutyS0ZQ/station?sort[][field]=stationNumber&sort[][direction]=desc
JSON資料解析
回傳的資料裡可以看到大括號內包著records,這個records是一個Array,Array裡每筆資料都有id跟fields兩個屬性,fields裡則有我們所需要的資料
自訂資料型別
模仿上面資料的格式自訂出一模一樣的型別去承接資料
畫面製作
整個是一個ViewController
- NavigationBar
- 底下是一個MapView上面覆蓋一個View裡面裝PickerView&ToolBar,初始設定為Hidden
- 使用View裝顯示紅橘線或輕軌的ImageView、顯示站點以及距離的Label、點擊功能的Button
- 顯示功能清單的TableView
KmrtKlrtFetcher
- shared:聲明static常數shared裡面存著KmrtKlrtFetcher,在ViewController直接使用內部function
- fetchKMRTLocationData:參數completion使用ResultType定義下載結果並回傳不同的資料
KMRTListViewController — fetchMRTData
在ViewController下載資料,當資料下載成功後儲存資料並將資料顯示出來,因為PickerView一開始dataSource在還沒資料時就會開始,所以在下載成功後reload把資料顯示出來
客製化的MKAnnotationView
使用MKMapViewDelegate的function,這個function需要回傳一個MKAnnotationView?
- 因為他會將地圖上所有的圖標都做出改變,所以我們如果希望使用者圖標不要改變,就先檢查是否是使用者,如果是就回傳nil即可
- 我要以title辨別需要顯示什麼樣顏色的圖標,我們可以從function的參數annotation取得我們正在客製化的annotation,每一個annotation都會進來執行一次
- 使用MKMarkerAnnotationView取得要改變的annotation的annotationView
- 改變annotationView的屬性實現客製化最後回傳
關於客製化MKAnnotationView參考連結:
地圖上畫出路線 — MKOverlayRenderer
createLinePath — 先建立路線的Path並加入到MapView的Overlay
- 參數傳入要加入Overlay的MapView、起點終點座標、completion加入後要做的事
- 使用MKPlacemark將兩點座標帶入做出地標
- 使用MKMapItem將MKPlacemark帶入,初始出一個MKMapItem
- 使用MKDirections.request去request要計算兩點的路程,可以透過.transportType選擇走路或是開車的方式,把request帶入到MKDirections(request:)初始出一個MKDirections
- 使用MKDirections.calculate去計算路程會得到response跟error,可以從response.routes取得路線組,routes[0]取得第一條路線
- 使用map.addOverlay加入路線
- 然後為了在選定到定點時讓地圖跟著兩點進行縮放,先取得rect後使用completion,在使用者選定點後再去帶入兩點座標去縮放大小
MKMapViewDelegate
使用delegate的function將Overlay上色,沒有使用這個function設定的話,在地圖上是看不到路線的
移除路線
當切換站點時會畫出新的路線但原本的路線並不會因此消失,可以使用下面的方法先移除再畫出新的路線,使用overlays[0]取得地圖上的overlay並移除
kmrtStationMapView.removeOverlay(kmrtStationMapView.overlays[0])
地圖導航 — MapItem
- 藍色區塊是主要程式
- 取得終點位置座標並放進MKMapItem內,MKMapItem可以設定屬性name,點開地圖後該地標顯示的位置名稱
- 使用MKMapItem.forCurrentLocation取得使用者當前位置
- 將兩點存成一個MKMapItem的Array
- 使用MKMapItem.openMaps切換到地圖,並顯示兩點的導航然後可以設定路線模式,例如:開車、走路…等等
操作畫面
參考連結:
MKPlacemark
MKMapItem
MKMarkerAnnotationView
MKPolylineRenderer
切換到地圖導航
在MapView上畫出路線
GitHub連結: