高雄公共運輸App:Part4-高雄捷運功能頁

顯示離使用者最近的站點以及在地圖加入路線

Poga
彼得潘的 Swift iOS / Flutter App 開發教室
8 min readFeb 19, 2022

--

功能

  1. 包含紅橘兩線以及環狀輕軌三種路線供選擇
  2. 初始會顯示離使用者最近的站點,以及顯示路線在地圖上
  3. 點擊導航Button可跳出地圖顯示導航
  4. 下方清單顯示主要三個功能

作法

本篇會著重在1~4的分享,對5~7有興趣的可以去看Part.3

  1. 使用Airtable建立所有站點資訊並載入到App中
  2. 使用MKMapViewDelegate客製化MKAnnotationView做出不一樣的圖標
  3. 使用MKOverlayRenderer畫出路線
  4. 使用MKMapItem跳出地圖並顯示導航
  5. 使用CLLocationManger追蹤使用者位置
  6. 使用UIPickerView顯示站點清單
  7. 使用sorted(by:)找出距離最近的站點

Airtable API

因為高雄捷運、輕軌沒有提供完整的站點資料,所以自己用Airtable建立資料,包含:紅橘線、輕軌(種類)、站號、站名(中英文名稱)、經緯度、轉乘站,關於Airtable串接API可以參考我之前寫過的訂飲料App文章,裡面有更詳細的解釋

訂飲料App文章

API網址

sort[][field]=stationNumber這段是我希望他回傳的資料排序是以站號排序

sort[][direction]=desc這段則是希望他由大到小排序

JSON資料解析

回傳的資料裡可以看到大括號內包著records,這個records是一個Array,Array裡每筆資料都有id跟fields兩個屬性,fields裡則有我們所需要的資料

自訂資料型別

模仿上面資料的格式自訂出一模一樣的型別去承接資料

畫面製作

整個是一個ViewController

  1. NavigationBar
  2. 底下是一個MapView上面覆蓋一個View裡面裝PickerView&ToolBar,初始設定為Hidden
  3. 使用View裝顯示紅橘線或輕軌的ImageView、顯示站點以及距離的Label、點擊功能的Button
  4. 顯示功能清單的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並移除

地圖導航 — MapItem

  • 藍色區塊是主要程式
  1. 取得終點位置座標並放進MKMapItem內,MKMapItem可以設定屬性name,點開地圖後該地標顯示的位置名稱
  2. 使用MKMapItem.forCurrentLocation取得使用者當前位置
  3. 將兩點存成一個MKMapItem的Array
  4. 使用MKMapItem.openMaps切換到地圖,並顯示兩點的導航然後可以設定路線模式,例如:開車、走路…等等

操作畫面

--

--