Map8 Navigation SDK for iOS
Map8 Navigation SDK 提供一個完整的導航畫面:只要給目的地,就能在您的 App 裡開啟逐向導航,不需要自己處理路線規劃、GPS 貼路與畫面。
內建功能:
- 路線規劃與路線預覽(總時間、距離、主要道路、路線列表)
- 逐向轉彎提示、「接著」下一個轉彎、路口實景圖
- 車道指示:接近路口時顯示建議車道
- 測速照相提醒(一般測速、區間測速、科技執法)與道路速限
- 中文語音導航
- 偏離路線自動重新規劃
- 隧道內 GPS 斷訊推算:收不到 GPS 時沿路線推算位置,車標與語音照常進行
- 日間/夜間外觀自動切換(依日出日落)
- 立體/平面兩種導航視角,可在導航中切換
- 直向與橫向畫面
- 背景導航(鎖屏或切換到其他 App 時,定位與語音持續運作)
- 可自訂的配色
畫面版面是固定的,您可以調整配色、接收導航事件,並決定導航畫面要如何呈現在您的 App 中。
系統需求
- iOS 16.4 以上
- Xcode 26 以上
- Swift(Navigation SDK 的介面僅提供 Swift 版本)
- 已申請的 Map8 Key
版本相容性
| Navigation SDK | 搭配的 Map8 Maps SDK(Map8.xcframework) |
|---|---|
| 1.1.1 | 1.0.4 以上 |
語言
導航畫面的文字與語音播報目前只提供繁體中文。
安裝
加入 framework
Navigation SDK 由以下三個 framework 組成,請一併加入您的 Xcode 專案:
| Framework | 說明 |
|---|---|
Map8.xcframework |
Map8 地圖 SDK(安裝方式見 Maps SDK 安裝指南) |
Map8Navigation.xcframework |
導航畫面與導航流程 |
M8TurnLib.xcframework |
導航引擎 |
下載 Navigation SDK:https://api.map8.zone/download/navigation_sdk/map8-navigation-sdk-ios.zip?key=您的key
將解壓縮後的 Map8Navigation.xcframework 與 M8TurnLib.xcframework 拖曳加入您的專案,前往 General 頁籤,在 Frameworks, Libraries, and Embedded Content 區塊確認三個 framework 都已加入,並將 Embed 選項設為 Embed & Sign。
設定 Map8 Key
在 App 啟動時設定一次 Map8 Key(地圖與導航共用同一把 Key):
import UIKit
import Map8
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
MGLAccountManager.map8Key = "您的 Map8 Key"
return true
}
}
也可以沿用地圖 SDK 的方式,在 Info.plist 加入 Map8Key,兩者擇一即可。
Info.plist 設定
定位權限(必要)
加入 Privacy - Location When In Use Usage Description,說明 App 為什麼需要定位,例如:
導航需要取得您的位置
背景導航(建議)
加入 Required background modes(UIBackgroundModes),並勾選以下兩項:
| 項目 | 用途 |
|---|---|
App registers for location updates(location) |
鎖屏或切換到其他 App 時繼續定位 |
App plays audio or streams audio/video using AirPlay(audio) |
在背景播報語音導航 |
快速開始
建立 Map8NavigationViewController,設定目的地後呈現出來,再呼叫 startNavigation():
import UIKit
import CoreLocation
import Map8Navigation
class ViewController: UIViewController, Map8NavigationViewControllerDelegate {
func startNavigation() {
let destination = Map8NavigationDestination(
coordinate: CLLocationCoordinate2D(latitude: 25.102355, longitude: 121.548493),
name: "國立故宮博物院",
address: "台北市士林區至善路二段221號"
)
let navigation = Map8NavigationViewController(destination: destination)
navigation.delegate = self
navigation.modalPresentationStyle = .fullScreen
present(navigation, animated: true)
navigation.startNavigation()
}
// 使用者按了結束導航(抵達時會先顯示抵達畫面,按「完成」後 SDK 預設會自動關閉)
func navigationViewController(_ controller: Map8NavigationViewController,
didEndWith reason: Map8NavigationEndReason) {
if reason == .cancelled {
controller.dismiss(animated: true)
}
}
// 無法導航(沒有定位權限、路線規劃失敗):一定要處理,否則畫面會停在原地
func navigationViewController(_ controller: Map8NavigationViewController,
didFailWith error: Map8NavigationError) {
controller.dismiss(animated: true)
}
}
執行後的流程:
- 取得使用者目前位置,規劃到目的地的路線
- 顯示路線預覽:整條路線、總時間、距離、主要道路、路線列表
- 使用者按下「開始導航」,進入逐向導航
- 抵達目的地時顯示抵達畫面,使用者按「完成」後關閉導航畫面
呈現方式
請以全螢幕(.fullScreen)呈現導航畫面。使用預設的卡片式(sheet)呈現時,使用者往下滑就能關掉畫面;這種情況 SDK 會自動結束導航並呼叫 didEndWith: .cancelled,但導航會被意外中斷。
在 SwiftUI 中使用
用 UIViewControllerRepresentable 包裝,並以 fullScreenCover 呈現:
import SwiftUI
import CoreLocation
import Map8Navigation
// 不要命名為 NavigationView,會跟 SwiftUI 內建的 NavigationView 衝突。
struct Map8NavigationScreen: UIViewControllerRepresentable {
let destination: Map8NavigationDestination
let onClose: () -> Void
func makeUIViewController(context: Context) -> Map8NavigationViewController {
let controller = Map8NavigationViewController(destination: destination)
controller.delegate = context.coordinator
controller.startNavigation()
return controller
}
func updateUIViewController(_ controller: Map8NavigationViewController, context: Context) {}
func makeCoordinator() -> Coordinator { Coordinator(onClose: onClose) }
final class Coordinator: Map8NavigationViewControllerDelegate {
let onClose: () -> Void
init(onClose: @escaping () -> Void) { self.onClose = onClose }
func navigationViewController(_ controller: Map8NavigationViewController,
didEndWith reason: Map8NavigationEndReason) {
if reason == .cancelled { onClose() }
}
// 抵達畫面按「完成」:由 SwiftUI 關閉,不要讓 SDK 自己 dismiss
func navigationViewControllerDidFinish(_ controller: Map8NavigationViewController) {
onClose()
}
func navigationViewController(_ controller: Map8NavigationViewController,
didFailWith error: Map8NavigationError) {
onClose()
}
}
}
struct ContentView: View {
@State private var isNavigating = false
var body: some View {
Button("開始導航") { isNavigating = true }
.fullScreenCover(isPresented: $isNavigating) {
Map8NavigationScreen(
destination: Map8NavigationDestination(
coordinate: CLLocationCoordinate2D(latitude: 25.102355, longitude: 121.548493),
name: "國立故宮博物院"
),
onClose: { isNavigating = false }
)
.ignoresSafeArea()
}
}
}
範例 App
我們提供一個完整的範例 App,示範目的地搜尋、導航、模擬導航,以及路線偏好、日夜間、導航視角、路線預覽、自訂配色等設定。
下載範例 App:https://api.map8.zone/download/navigation_sdk/map8-navigation-sdk-ios-sample.zip?key=您的key
壓縮檔內已附所需的 framework,解壓縮後:
- 開啟
Map8NavigationSample.xcodeproj - 在
SampleApp.swift把YOUR_MAP8_KEY換成您的 Map8 Key - 在
Signing & Capabilities選擇您的開發團隊(Team),必要時修改 Bundle Identifier - 接上 iPhone 或選擇模擬器執行
| 檔案 | 內容 |
|---|---|
SampleApp.swift |
設定 Map8 Key |
ContentView.swift |
首頁:目的地、開始導航、模擬導航、各項設定 |
NavigationScreen.swift |
在 SwiftUI 中使用 Map8NavigationViewController、處理導航事件 |
PlaceSearch.swift |
用 Map8 地點搜尋 API 找目的地 |
路線預覽
預設在規劃完成後先顯示路線預覽,使用者確認後才開始導航。
// 關掉預覽:規劃完成後直接開始導航
navigation.showsRoutePreview = false
如果您想自己設計預覽畫面,可以關掉內建預覽,從 didPlanRoute 取得路線摘要,使用者確認後再呼叫 startGuidance():
func navigationViewController(_ controller: Map8NavigationViewController,
didPlanRoute summary: Map8NavigationRouteSummary) {
print("總距離 \(summary.distance) 公尺,約 \(Int(summary.duration / 60)) 分鐘")
print("經 \(summary.mainRoads().joined(separator: "、"))")
for step in summary.steps {
print("\(step.roadName) \(step.distance) 公尺")
}
}
// 使用者在您的預覽畫面按下開始
navigation.startGuidance()
路線偏好
在 startNavigation() 之前設定,導航中偏離路線重新規劃時也會沿用:
navigation.routePreference = .avoidHighways
| 值 | 說明 |
|---|---|
.fastest |
最佳路徑(預設) |
.shortest |
最短距離 |
.preferFreeway1 |
國道一號優先 |
.preferFreeway3 |
國道三號優先 |
.avoidHighways |
避走高速公路 |
導航畫面操作
鏡頭模式
| 模式 | 說明 |
|---|---|
| 跟隨 | 預設,鏡頭跟著車子移動 |
| 自由 | 使用者拖曳、縮放、旋轉地圖後進入;畫面出現「回到導航」按鈕,停止操作 10 秒後自動回到跟隨 |
| 全覽 | 使用者按下全覽按鈕後進入,顯示剩下的路線;按「回到導航」回到跟隨 |
// 自動回到導航的秒數,nil = 不自動回來
navigation.autoRecenterDelay = 15
// 用程式碼切換
navigation.showRouteOverview()
navigation.recenter()
導航視角
導航中的鏡頭有兩種視角:
| 視角 | 說明 |
|---|---|
.tilted 立體 |
預設,鏡頭往前傾斜,看得到前方較遠的路 |
.topDown 平面 |
從正上方往下看,車頭朝上 |
navigation.cameraPerspective = .topDown
// 在畫面上顯示切換按鈕(預設不顯示),讓使用者在導航中自己切換
navigation.showsPerspectiveButton = true
導航途中也可以修改 cameraPerspective,鏡頭會用動畫轉過去。路線預覽與全覽固定是平面,不受這個設定影響。
使用者按切換按鈕時會呼叫 delegate,可以在這裡記住使用者的選擇,下次導航時設定回 cameraPerspective:
func navigationViewController(_ controller: Map8NavigationViewController,
didChange cameraPerspective: Map8NavigationCameraPerspective) {
// 例如存到 UserDefaults
}
語音
navigation.isVoiceMuted = true
畫面上的語音按鈕也可以切換靜音。
語音播報時會自動降低其他 App 的音樂音量、暫停 Podcast,播完再恢復。
結束導航
畫面左下角內建結束按鈕。如果您想自己提供結束方式,可以關掉內建按鈕:
navigation.showsEndButton = false
// 在您自己的按鈕裡
navigation.stopNavigation()
抵達
抵達目的地時預設顯示抵達畫面(已抵達目的地、名稱、地址、「完成」按鈕)。使用者按「完成」後會呼叫 navigationViewControllerDidFinish,沒有實作時預設會關閉導航畫面(dismiss)。
// 想自己處理抵達後的畫面
navigation.showsArrivalScreen = false
func navigationViewController(_ controller: Map8NavigationViewController,
didEndWith reason: Map8NavigationEndReason) {
if reason == .arrived {
// 顯示您自己的抵達畫面
}
}
外觀
日間/夜間
預設依目的地的日出日落時間自動切換,夜間會改用深色地圖與較暗的面板。
navigation.appearance = .automatic // 預設,依日出日落切換
navigation.appearance = .light // 一律日間
navigation.appearance = .dark // 一律夜間
配色
可以把導航畫面調整成您的品牌色。日間與夜間各一組配色,隨時修改都會立即套用。
var scheme = Map8NavigationColorScheme.default
scheme.routeLine = .systemGreen
scheme.accent = .systemGreen
navigation.colorScheme = scheme
// 夜間另外設定,不設定則使用內建的夜間配色
navigation.nightColorScheme = .night
| 欄位 | 說明 |
|---|---|
panelBackground |
主要面板底色:轉彎卡片、下方資訊列、測速警示 |
secondaryPanelBackground |
次要面板底色:「接著」那一列、狀態提示 |
panelText |
面板文字與轉彎圖示、車道箭頭 |
warning |
接近測速照相、超速時閃爍的警示色 |
routeLine |
尚未走過的路線(外框會自動調暗) |
traveledRouteLine |
已經走過的路線(外框會自動調暗) |
accent |
強調色:車標箭頭、浮動按鈕圖示 |
floatingButtonBackground |
浮動按鈕底色 |
橫向畫面
導航畫面支援直向與橫向:橫向時資訊集中在左側,右側留給地圖。您的 App 需要在 General → Deployment Info 開啟橫向(Landscape Left / Right),導航畫面才會跟著轉向;只支援直向的 App 則維持直向顯示。
模擬導航
開發或測試時,可以不用實際移動,讓 SDK 沿著路線自動產生定位。模擬的定位與真實 GPS 走同一套流程。
navigation.simulation = Map8NavigationSimulation(
origin: CLLocationCoordinate2D(latitude: 25.075828, longitude: 121.574365),
speedKmh: 50,
playbackRate: 4 // 4 倍速
)
navigation.startNavigation()
導航事件
實作 Map8NavigationViewControllerDelegate 接收導航事件,所有方法都是選用的,只實作需要的即可。所有方法都在主執行緒呼叫,可以直接更新 UI。
// ViewController 已在宣告處加上 Map8NavigationViewControllerDelegate(見「快速開始」),
// 這裡只是把方法放在 extension 裡整理,不要再重複宣告一次協定。
extension ViewController {
func navigationViewController(_ controller: Map8NavigationViewController,
didPlanRoute summary: Map8NavigationRouteSummary) {
// 路線規劃完成
}
func navigationViewControllerDidStartNavigation(_ controller: Map8NavigationViewController) {
// 使用者按下開始導航
}
func navigationViewController(_ controller: Map8NavigationViewController,
didUpdate progress: Map8NavigationProgress) {
// 每收到一筆定位呼叫一次(通常約每秒一次):剩餘距離、剩餘時間、目前路名、車速
}
func navigationViewControllerDidReroute(_ controller: Map8NavigationViewController) {
// 偏離路線後已重新規劃
}
func navigationViewController(_ controller: Map8NavigationViewController,
didEndWith reason: Map8NavigationEndReason) {
// 抵達(.arrived)或使用者結束(.cancelled)
}
func navigationViewControllerDidFinish(_ controller: Map8NavigationViewController) {
// 使用者在抵達畫面按下「完成」
controller.dismiss(animated: true)
}
func navigationViewController(_ controller: Map8NavigationViewController,
didFailWith error: Map8NavigationError) {
// 無法導航:沒有定位權限,或路線規劃失敗
controller.dismiss(animated: true)
}
func navigationViewController(_ controller: Map8NavigationViewController,
didChange cameraMode: Map8NavigationCameraMode) {
// 鏡頭模式改變(跟隨/自由/全覽)
}
func navigationViewController(_ controller: Map8NavigationViewController,
didChange cameraPerspective: Map8NavigationCameraPerspective) {
// 使用者按切換按鈕,改變了導航視角(立體/平面);用程式設定不會呼叫
}
}
API 參考
Map8NavigationViewController
建立
| 介面 | 說明 |
|---|---|
init(destination:) |
以目的地建立導航畫面 |
屬性
| 屬性 | 型別 | 預設 | 說明 |
|---|---|---|---|
delegate |
Map8NavigationViewControllerDelegate? |
nil |
導航事件 |
destination |
Map8NavigationDestination |
— | 目的地,下次 startNavigation() 生效 |
routePreference |
Map8NavigationRoutePreference |
.fastest |
路線偏好 |
showsRoutePreview |
Bool |
true |
規劃完先顯示路線預覽 |
showsArrivalScreen |
Bool |
true |
抵達時顯示抵達畫面 |
showsEndButton |
Bool |
true |
顯示內建的結束導航按鈕 |
cameraPerspective |
Map8NavigationCameraPerspective |
.tilted |
導航視角 |
showsPerspectiveButton |
Bool |
false |
顯示立體/平面切換按鈕 |
isVoiceMuted |
Bool |
false |
語音靜音 |
autoRecenterDelay |
TimeInterval? |
10 |
自由模式停止操作後自動回到導航的秒數 |
appearance |
Map8NavigationAppearance |
.automatic |
日間/夜間外觀 |
colorScheme |
Map8NavigationColorScheme |
.default |
日間配色 |
nightColorScheme |
Map8NavigationColorScheme |
.night |
夜間配色 |
styleURL / nightStyleURL |
URL |
Map8 預設樣式 | 日間/夜間地圖樣式 |
simulation |
Map8NavigationSimulation? |
nil |
模擬導航(開發測試用) |
routeSummary |
Map8NavigationRouteSummary? |
唯讀 | 目前路線摘要 |
cameraMode |
Map8NavigationCameraMode |
唯讀 | 目前鏡頭模式 |
isNavigating |
Bool |
唯讀 | 是否正在導航中(含規劃路線中) |
isNightAppearance |
Bool |
唯讀 | 目前是否為夜間外觀 |
方法
| 方法 | 說明 |
|---|---|
startNavigation() |
開始:規劃路線,依設定顯示預覽或直接導航 |
startGuidance() |
從路線預覽進入導航(自行設計預覽畫面時使用) |
stopNavigation() |
結束導航,通知 didEndWith: .cancelled |
recenter() |
回到導航視角 |
showRouteOverview() |
全覽剩下的路線 |
資料型別
Map8NavigationDestination
| 欄位 | 型別 | 說明 |
|---|---|---|
coordinate |
CLLocationCoordinate2D |
目的地座標 |
name |
String |
名稱,選填(顯示在抵達畫面,不影響選路) |
address |
String |
地址,選填(顯示在抵達畫面,不影響選路) |
Map8NavigationRouteSummary
| 欄位 | 型別 | 說明 |
|---|---|---|
distance |
Int |
總距離(公尺) |
duration |
TimeInterval |
預估總時間(秒) |
steps |
[Map8NavigationRouteStep] |
每一個步驟 |
mainRoads(limit:) |
[String] |
主要道路(距離最長的幾條路名) |
Map8NavigationRouteStep
| 欄位 | 型別 | 說明 |
|---|---|---|
roadName |
String |
道路名稱 |
distance |
Int |
這一段的長度(公尺) |
maneuver |
Map8NavigationManeuver |
這一段結束時的轉彎 |
Map8NavigationProgress
| 欄位 | 型別 | 說明 |
|---|---|---|
distanceRemaining |
Int |
剩餘距離(公尺) |
durationRemaining |
TimeInterval |
剩餘時間(秒) |
currentRoadName |
String |
目前道路名稱 |
speedKmh |
Int |
目前車速(km/h) |
Map8NavigationSimulation
| 欄位 | 型別 | 預設 | 說明 |
|---|---|---|---|
origin |
CLLocationCoordinate2D |
— | 模擬起點 |
speedKmh |
Double |
50 |
模擬車速 |
playbackRate |
Double |
1 |
播放倍速 |
列舉
| 型別 | 值 |
|---|---|
Map8NavigationEndReason |
.arrived 抵達、.cancelled 使用者結束 |
Map8NavigationError |
.locationPermissionDenied 沒有定位權限、.routeFailed(Error) 路線規劃失敗 |
Map8NavigationCameraMode |
.following 跟隨、.free 自由、.overview 全覽 |
Map8NavigationCameraPerspective |
.tilted 立體、.topDown 平面 |
Map8NavigationAppearance |
.automatic 自動、.light 日間、.dark 夜間 |
Map8NavigationManeuver |
.turnLeft、.turnRight、.uTurnLeft、.uTurnRight、.keepLeft、.keepRight、.straight |
網路與隱私
連線網域
Navigation SDK 會連線到以下網域,如果您的網路環境有白名單限制,請一併開放:
| 網域 | 用途 |
|---|---|
api.map8.zone |
地圖圖資與樣式 |
nav8.pakka.ai |
路線規劃、路口實景圖 |
收集的資料
為了規劃路線,SDK 會將以下資料傳送到路線規劃伺服器,僅用於導航功能本身,不做跨 App 追蹤:
| 資料 | 用途 |
|---|---|
| 精確位置 | 規劃路線的起點、偏離路線後重新規劃 |
| 目的地座標,以及目的地名稱、地址的前 5 個字 | 規劃路線的終點;名稱與地址僅供伺服器記錄,不影響選路 |
| 裝置識別碼 | 取得路線規劃服務的存取權杖 |
SDK 已內附 Apple 規定的隱私清單(PrivacyInfo.xcprivacy),Xcode 產生 App 的隱私報告時會自動包含。填寫 App Store 的 App 隱私權資訊時,請將「精確位置」與「裝置 ID」列入,用途為「App 功能」。
常見問題
進入隧道後車標還會動嗎?
會。導航中超過 2 秒收不到 GPS,SDK 會沿著路線依進隧道前的車速推算位置,車標、語音與區間測速倒數照常進行;GPS 恢復後立即改回真實位置。若隧道內減速或塞車,出隧道時車標可能會往回修正一下。
偏離路線時會怎麼樣?
偏離路線超過 35 公尺並持續 5 秒,SDK 會播報「重新規劃路線」並自動規劃新路線,同時沿用原本的路線偏好。
沒有定位權限會怎麼樣?
使用者拒絕定位權限時,導航會結束並呼叫 didFailWith: .locationPermissionDenied,您可以在這裡引導使用者到設定開啟權限。
台灣圖霸感謝您的支持與愛護!
有任何疑問,或是指教,都非常歡迎您找我們詢問。
非常感謝!









