iOS CarPlay|WWDC22 - 通過 CarPlay 讓你的 App 發揮更大的作用
本文是對 WWDC22|10016 - Get more mileage out of your app with CarPlay 的梳理。
🐞 關鍵詞:CarPlay Simulator、Fueling App、Driving Task App、Instrument Cluster;📝 字數:4k+
概要
時隔 2 年,CarPlay 終於更新了。以下是該 session 的主要內容:
- 介紹 iOS16 中新增的兩種支援 CarPlay 的 App 型別:Fueling App 和 Driving Task App
- 探索 Navigation App 如何在受支援車輛中的數字儀表盤上實時繪製地圖
- 🌟 CarPlay Simulator:全新的 CarPlay App 開發與測試工具。它可以幫助你在不離開辦公桌的情況下連線 iPhone Device 來開發和測試 CarPlay App,模擬真實環境,而無需經常來回跑到你的車上或購買售後市場主機進行測試
- 簡單演示使用 CarPlay Simulator 對 CarPlay App 進行測試
注|本文中除 CarPlay App
外,單獨出現的 App
均指 iPhone App
。
新增兩種支援 CarPlay 的 App 型別:Fueling App 和 Driving Task App
題外話|CarPlay 是為駕駛員打造的,當你在構建 CarPlay App 時,你應該考慮的主要使用者是駕駛員。因此,你應該只在 CarPlay 上啟用與駕駛時相關的功能,忽略在駕駛時不應該做的任何功能,忽略複雜的、不常見的功能。諸如一次性配置、登入或閱讀條款等事情最好在駕駛之前或之後執行,因此它們不應該出現在你的 CarPlay App 中。請注意,你的 App 需要授權才能顯示在 CarPlay 中。你可以在 Apple CarPlay Developer 上根據你的 App 型別申請授權。
在這之前,有 6 種支援 CarPlay 的 App 型別:
今年,Apple 新增了 2 種支援 CarPlay 的 App 型別:Fueling App 和 Driving Task App。
題外話|Templates
Templates(模版)是在 CarPlay App 呈現 UI 的方式。你的 CarPlay App 負責提供資料,Templates 負責代表你將 UI 繪製到汽車的顯示屏上。你的 CarPlay App 可以很方便地接入 Templates,並且有幾個好處:
- Templates UI 不像 UIKit UI 那樣可高度定製化,不用擔心設計給你花裡胡哨的介面了。Templates UI 的複雜度低,通過簡單的 Templates API 即可讓你在 CarPlay App 中呈現 UI
- 不必擔心字型大小問題,Templates 會自己適配不同的汽車顯示屏
- 使用 Templates,你的 CarPlay App UI 與其他 CarPlay App UI 風格保持一致,可以讓你的使用者更容易上手使用你的 CarPlay App
- Templates 會負責確保你的 CarPlay App UI 在任何支援 CarPlay 的汽車中都能正常呈現和使用,無論汽車中使用的顯示屏型別和大小如何
總之,Templates 會為你處理大部分工作。
在構建 CarPlay App 時,有多種 Templates 可供選擇。例如,顯示按鈕陣列的 Grid Template(下圖第 1 行第 4 個),顯示錶格的 List Template (下圖第 2 行第 1 個)等等。
無論作為開發人員還是 iOS 使用者,你都應該熟悉這些 Templates。最重要的是,你的 CarPlay 使用者會熟悉它們,因為它們出現在整個 CarPlay 車載中。
有些 Templates 是所有 App 型別通用的,而有些 Templates 僅限於特定型別的 App 才能使用。具體可以通過以下圖表檢視。
Fueling App
EV Charging App|EV Charging App 是 Apple 在 iOS14 新增的支援 CarPlay 的 App 型別。這類 App 可以用於查詢電車充電站的位置,還可以幫助駕駛員將汽車連線到正確的充電站並啟動它。
這種型別的功能不僅適用於電車,它還適用於油車。於是 Apple 今年讓 Fueling App 也支援了 CarPlay,主要用於幫助駕駛員給汽車加油。請注意,Fueling CarPlay App 除了支援查詢加油站位置外,還應該有啟動加油機等功能。
Driving Task App
Driving Task App 是一種新型 CarPlay App,它可以支援各種各樣可以完成簡單任務的 App。 但你仍然需要注意的是,這些 CarPlay App 的主要目的必須是實現駕駛員在駕駛時需要完成的任務,它是用於真正有助於駕駛的任務,而不僅僅是在你(開發者)駕駛時需要完成的任務。
以下是屬於此型別的一些 App 示例:
- 幫助控制汽車配件的 App
- 提供駕駛或道路狀態和資訊的 App
- 在駕駛開始或結束時幫助完成任務的 App
下面讓我們看一些更具體的例子。
Road Status App
Road Status App 可以通知使用者重要的道路資訊。這個 CarPlay App 是使用 CPPointOfInterestTemplate 構建的。注意,使用此 CarPlay App 的使用者正在開車,因此這樣的 CarPlay App 應該提供一個非常簡短的使用者當前所在位置附近的重要的道路資訊列表。這不適用於幫助使用者在開車前進行完整路線規劃的 App。
在這個 CarPlay App 中,這是使用者在選擇位置時看到的內容,提示資訊建議言簡意賅。
Trailer Controller App
Trailer Controller App 可以用於控制汽車配件。這個 CarPlay App 使用 CPInformationTemplate 提供有關已連線配件的基本資訊,並提供了兩個按鈕來給使用者採取操作。這個 CarPlay App 的 UI 和功能就是如此簡單。當然,該 iPhone App 還有許多其他功能,但與駕駛不相關的功能不在 CarPlay App 中提供。使用者可以在離開車輛或停車時使用該 iPhone App 中的更多功能。
Mileage Logger、Express Lane
最後,讓我們看幾個使用 CPGridTemplate 的示例。
Mileage Logger 是一個非常簡單的 CarPlay App,就只有兩個按鈕。它支援讓駕駛員將他們的里程記錄為個人里程或商務里程。此 App 非常適合新的 Driving Task App 型別,因為它可以讓使用者在駕駛時非常方便地完成簡單的任務。
Express Lane App 與 Mileage Logger App 的 UI 近似,它是一個快速車道收費應答器 CarPlay App,使用 CPGridTemplate 讓使用者選擇車內有多少名乘客。這個 CarPlay App 的功能也非常簡單方便,也是一個完美的 Driving Task App。
小結
回顧一下,在設計你的 Driving Task App 時,你需要注意以下幾點:
- 一定要考慮製作一個單屏 CarPlay App,提供在駕駛時所需的最少功能
- 只提供可以在幾秒鐘內完成的功能
- 避擴音供複雜或不常用的功能,例如首次設定或詳細配置等
- 不應該提供駕駛時不需要的功能,即使它與汽車相關
探索 Navigation App 如何在受支援車輛中的數字儀表盤上實時繪製地圖
CarPlay Dashboard|在 iOS 13 中,Apple 添加了 API 以支援 Navigation App 在 CarPlay Dashboard 中繪製地圖。你可以編輯 Info.plist 來新增宣告對 Dashboard 的支援,並新增所需的 Scene session role,然後實現所需的 delegate。當 Navigation CarPlay App 在 Dashboard 中出現或消失時,系統會通知你的 delegate,並將 UIWindow 傳遞給你,你可以在其中繪製地圖內容。
如果你之前已經對 Dashboard 做了支援,那麼新增對 Instrument Cluster 的支援將是小菜一碟,因為它的實現方式與 Dashboard 類似。
首先在 Info.plist 的 Application scene manifest 中新增宣告對 Instrument Cluster 的支援(CPSupportsInstrumentClusterNavigationScene = true
),並新增所需的 Scene session role。
xml
<key>UIApplicationSceneManifest</key>
<dict>
<!-- Indicate support for CarPlay dashboard -->
<key>CPSupportsDashboardNavigationScene</key>
<true/>
<!-- Indicate support for instrument cluster displays -->
<key>CPSupportsInstrumentClusterNavigationScene</key>
<true/>
<!-- Indicate support for multiple scenes -->
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
<key>UISceneConfigurations</key>
<dict>
<!-- For device scenes -->
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>UIWindowScene</string>
<key>UISceneConfigurationName</key>
<string>Phone</string>
<key>UISceneDelegateClassName</key>
<string>MyAppWindowSceneDelegate</string>
</dict>
</array>
<!-- For the main CarPlay scene -->
<key>CPTemplateApplicationSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>CPTemplateApplicationScene</string>
<key>UISceneConfigurationName</key>
<string>CarPlay</string>
<key>UISceneDelegateClassName</key>
<string>MyAppCarPlaySceneDelegate</string>
</dict>
</array>
<!-- For the CarPlay Dashboard scene -->
<key>CPTemplateApplicationDashboardSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>CPTemplateApplicationDashboardScene</string>
<key>UISceneConfigurationName</key>
<string>CarPlay-Dashboard</string>
<key>UISceneDelegateClassName</key>
<string>MyAppCarPlayDashboardSceneDelegate</string>
</dict>
</array>
<!-- For the CarPlay instrument cluster scene -->
<key>CPTemplateApplicationInstrumentClusterSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>CPTemplateApplicationInstrumentClusterScene</string>
<key>UISceneConfigurationName</key>
<string>CarPlay-Instrument-Cluster</string>
<key>UISceneDelegateClassName</key>
<string>MyAppCarPlayInstrumentClusterSceneDelegate</string>
</dict>
</array>
</dict>
</dict>
然後實現你的 Application instrument cluster scene delegate。API 會提供一個 UIWindow 給你來繪製你的地圖內容,並在 Instrument Cluster 啟動和關閉時通知你。你可以將你的地圖實時繪製到 Instrument Cluster 中。
```swift extension TemplateApplicationSceneDelegate: CPTemplateApplicationInstrumentClusterSceneDelegate {
func templateApplicationInstrumentClusterScene(
_ templateApplicationInstrumentClusterScene: CPTemplateApplicationInstrumentClusterScene,
didConnect instrumentClusterController: CPInstrumentClusterController) {
// Connected to Instrument Cluster
TemplateManager.shared.clusterController(instrumentClusterController, didConnectWith: templateApplicationInstrumentClusterScene.contentStyle)
}
…
func instrumentClusterControllerDidConnect(_ instrumentClusterWindow: UIWindow) {
// Window in which to draw instrument cluster contents
self.instrumentClusterWindow = instrumentClusterWindow
}
} ```
雖然對 Instrument Cluster 與 Dashboard 新增支援的實現非常相似,但有一些特定於 Instrument Cluster 的注意事項。
- 首先,Instrument Cluster 支援使用者放大和縮小地圖,因此你需要使用 CPInstrumentClusterControllerDelegate 在你的 CarPlay App 中實現此功能。
- 同樣,如果你的 CarPlay App 支援顯示指南針或速度限制,系統會在適當的時間通知你的 delegate 來繪製它們。
- 最後,請注意,你的 Instrument Cluster 檢視可能會被汽車 Instrument Cluster 中的其他元素部分遮擋。當然,iOS 已經有了一流的機制來處理這種事情,那就是安全區域。你可以在檢視控制器上重寫
viewSafeAreaInsetsDidChange
來監聽安全區域的改變,並在 Cluster View 上使用safeAreaLayoutGuide
以保證檢視區域中的關鍵內容可見而不被遮擋。
CarPlay Simulator
這是今年 CarPlay 更新的重磅,所有型別的 CarPlay App 都能用上它。
在這之前,你有 2 種方式來測試 CarPlay App:
- Xcode iPhone Simulator 內建有 CarPlay Window,可以很方便地快速測試你的 CarPlay App
- 通過將你的 iPhone Device 連線到支援 CarPlay 的汽車或售後市場主機上來測試 CarPlay App,這是之前在你的 iPhone Device 上測試 CarPlay App 的唯一方式
今年,Apple 給我們帶來了 CarPlay Simulator,它是一個 Mac App,可模擬汽車中的 CarPlay 的完整環境。你可以在 Apple 開發者網站上下載 Xcode 附加工具包 - Additional Tools for Xcode 14 beta。
然後開啟它,在 Hardware 資料夾下可以找到 CarPlay Simulator。
執行該 App,然後將你的 iPhone Device 通過資料線連線到你的 Mac,即可啟動 CarPlay。
注|你不需要升級 MacOS 系統及 Xcode 版本也能使用 CarPlay Simulator。
使用 CarPlay Simulator 有幾個好處:
- 當你使用 CarPlay Simulator 時,你的 iPhone device 已經連線到你的 Mac,你可以同時使用 Mac 上的其它開發工具,例如在 Xcode 中除錯或在 Instruments 中測試效能。
- 在現有的 iPhone Simulator 內建的 CarPlay Window 上無法測試某些場景。例如,你需要測試你的 Navigation App 的語音指令是否與汽車的原生音訊源(如 FM radio)正確混合,在這之前,你可能要經常來回跑到你的車上或購買售後市場主機進行測試。而現在,你可以使用 CarPlay Simulator,CarPlay 實際上是在你的 iPhone Device 上執行的,就像在汽車中一樣。這意味著你現在可以很方便的在辦公位上進行測試。
- 你還可以使用 CarPlay Simulator 來測試多種不同配置的汽車,例如在不同尺寸的顯示屏上進行測試。
下面來介紹下 CarPlay Simulator 如何使用。它的視窗介面由 3 個部分組成:
- 視窗中間是 CarPlay 檢視,模擬汽車顯示屏
- 視窗底部是模擬汽車中各種不同硬鍵和旋鈕的按鈕
- 視窗頂部有一些按鈕
- Configure:配置按鈕,點選將彈出一個具有更高階功能的輔助視窗,稍後詳細講解
- Limit UI Off/On:模擬限制 CarPlay 上的某些內容,例如縮短音訊 CarPlay App 中列表的內容
- Light/Dark UI:模擬在汽車的 CarPlay 中切換 UI 的深淺色外觀
- Light/Dark Map:模擬在汽車的 CarPlay 中切換地圖的深淺色外觀
- Connected/Disconnected:模擬 iPhone Device 與汽車 CarPlay 斷開連線或重新連線,而不需要拔插資料線。因為當你使用此按鈕時你的 iPhone Device 仍將保持與 Mac 的連線,所以你可以使用它在 Xcode 除錯 CarPlay Scene 的斷開連線或重新連線。
Configure
點選主視窗中的 Configure 按鈕即可開啟一個具有更高階功能的輔助視窗。
在 General tab 中,你可以設定 CarPlay 顯示屏的尺寸。如果你的 CarPlay App UI 僅由 Templates 組成,Templates 會負責確保你的 UI 在任何支援 CarPlay 的汽車都能正常呈現和使用,不過你仍然可以嘗試配置不同的尺寸來檢視你的 UI 在不同汽車中的顯示效果。但是,如果你的 App 是 Navigation App,那麼嘗試配置不同的尺寸大小和寬高比來測試並確保地圖繪製的程式碼正常工作是至關重要的。
以下是一些推薦的用於測試 Navigation App 的顯示尺寸:
- 800 x 480(default)
- 1280 x 720
- 900 x 1200
在 Cluster Display tab 中,你可以勾選 Instrument Cluster Display enabled 並點選 Restart Session 按鈕,這時候會開啟一個新的視窗,它用於模擬汽車的儀表盤顯示屏。
這個功能是與 Navigation App 相關的,儀表盤顯示屏用於在汽車儀表盤的視野中為駕駛員顯示地圖或轉向卡。
Restart Session 按鈕用於當你修改 Configure 中的配置後,使其立即生效,而不需要重新啟動 CarPlay Simulator。
以上就是 CarPlay Simulator 的相關內容,更多功能就交由你自己探索。
使用 CarPlay Simulator 對 CarPlay App 進行測試
啟動 CarPlay Simulator。
連線你的 iPhone Device 到 Mac,CarPlay 會隨之啟動。
如果你的 CarPlay App 為深淺色外觀提供了兩套 icon,那麼你可以通過 Light/Dark UI 按鈕來切換深淺色外觀,以進行測試。不過在此之前,你需要先到 CarPlay 設定中設定外觀模式為 自動
,而不是 始終深色模式
。
你可以在 Configure - General tab 中設定 CarPlay 顯示屏的尺寸,然後點選 Restart Session 按鈕就能使其立即生效,而無需重啟 Carplay Simulator,這很方便。你可以通過此功能來測試你的 CarPlay App 特別是 Navigation App 是否良好地適配了不同尺寸的汽車顯示屏。
你可以在 Cluster Display tab 中啟用 Instrument Cluster Display 來測試你的 Navigation App 對汽車 Instrument Cluster 的支援。
在你使用 CarPlay Simulator 對你的 CarPlay App 進行全面測試且情況良好後,你可以完全相信你的 CarPlay App 會在真正的汽車中執行良好。不過建議你還是去車上試一試。
Templates 會負責確保你的 CarPlay App UI 在任何支援 CarPlay 的汽車中上都能正常呈現和使用。
一些使用者可能會喜歡使用汽車的旋鈕來操作 CarPlay App。如果你已經使用 CarPlay Simulator 中的模擬旋鈕進行測試,那麼它在汽車中的表現也一定是不錯的。Templates 會幫你處理好旋鈕事件。
你還可以測試下你的 Navigation App 對汽車數字儀表盤的支援效果。對駕駛員來說,將實時地圖顯示在他的視線範圍內是非常棒的,使用你的 Navigation App 的駕駛員一定會喜歡它。
參考
- iOS CarPlay|使用 CarPlay 為你的 App 提速
- iOS CarPlay|WWDC22 - 通過 CarPlay 讓你的 App 發揮更大的作用
- iOS BugFix|接入 UIScene 遇到的一些問題及解決方案
- iOS 混編|為 Objective-C 新增列舉巨集,改善混編體驗
- iOS CarPlay|與你分享 CarPlay 音訊 App 的開發過程與細節
- iOS 混編|Objective-C override alloc 的相容性問題
- iOS 混編|為 Objective-C API 指定可空性
- iOS 混編|限制 API 可用性
- iOS 混編|為 Swift 改進 Objective-C API
- iOS 混編|為 Swift 重新命名 Objective-C API
- iOS 混編|將 Objective-C typedef NSString 作為 String 橋接到 Swift 中
- 「建議收藏」《Effective Objective-C 2.0》52 個知識點總結(下)
- 「建議收藏」《Effective Objective-C 2.0》52 個知識點總結(上)