区块链技术博客
www.b2bchain.cn

WWDC20 10635 – 使用CarPlay车载系统为你的App提速求职学习资料

本文介绍了WWDC20 10635 – 使用CarPlay车载系统为你的App提速求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

概述

CarPlay 作为iOS功能在汽车上的延伸,又被称作“车载iOS”。自2013年苹果在WWDC上介绍CarPlay以来,支持CarPlay的汽车品牌越来越多,在汽车中控台上使用QQ音乐和豆瓣电台不再是一件麻烦事。

从iOS12开始,CarPlay开发API被首次引入,开始支持第三方导航,如百度地图、Waze、Google Maps、高德地图,让习惯iOS设备的车主不再只有安卓系统车机一种选择了。

基于模板(template)

CarPlay作为一个车载系统,有一点和普通iOS App开发有很大不同。所有的CarPlay API都基于Apple预先设定好的“模板”,开发者不能像构建普通手机App那样自定义UI和功能。原因也很简单,车载系统是给汽车驾驶员而非乘客使用的,驾驶安全性必然是重中之重,使用预设的模板,能最大限度地限制开发者构建对驾驶员有任何打扰的功能,让应用严格按照苹果设定的流程来运行。当然,CarPlay目前提供了几种类型的模板对象,也可以构建出色的CarPlay应用。

新特性

iOS14中,CarPlay框架提供了一组全新的模板,并对现有模板进行了改进。

WWDC20 10635 - 使用CarPlay车载系统为你的App提速

  • 用于音频应用的新控件和新模板。

  • 用于即时通信应用的新控件。

  • 用于充电桩和停车应用的新模板。

  • 用于快餐订购的新模板。

音频应用

iOS14 引入了一些用于音频应用程序的新模板。通过这些新的音频模板,iOS14中的车载音频应用将会有更丰富的用户体验。在以前的版本中,构建CarPlay音频应用程序需要用到 playable content API。 在iOS 14中,该API将被弃用,而使用新引入的”音频模板”。

WWDC20 10635 - 使用CarPlay车载系统为你的App提速

重要原则

首先,我们回顾一下在CarPlay中构建应用程序时应牢记的一些设计原则。

  • 为驾驶员设计
  • 流线型交互
  • 复用App配置
  • 首先在CarPlay中启动

CarPlay是为驾驶员而非乘客而设计的。 应用程序需要从最常见的场景启动,并让每个交互操作简化成可以在几秒内完成的任务。同时,要尽可能复用主App中的各种配置,以最小化CarPlay场景下用户需要进行的任何操作。应用程序可能会首先在CarPlay中启动,并且只能在CarPlay中启动。当用户在CarPlay主屏幕上点击您的应用程序时,应用程序将连接到汽车场景,而不是iPhone场景。因此,消除应用程序中依赖于iPhone上启动的任何逻辑非常重要。

iOS13中,苹果引入了UIScene的概念,用于构建多窗口应用。在车载场景下,车机屏幕属于一个新的窗口,

使用UIScene可以轻松做到这一点。实际上,CarPlay应用必须采用UIScene才能使用CarPlay框架,因此必须从传统的UIWindow和UIApplicationDelegate API向UIScene过渡。

前面提到,iOS14以前,CarPlay构建音频应用程序,使用Playable content API来实现,系统使用音频元数据(如专辑和歌曲),来组装好播放器UI。如果你的应用还将支持iOS13,那么Playable content API和新的模板将同时存在。在iOS 13及更低版本上,系统将启动Playable content API的应用。在iOS14中,则使用音频模板。

在示例场景中,我们需要采用UIScene才能使用CarPlay模板。首先需要在Info.plist中声明一个scene。

// CarPlay Scene Manifest  <key>UIApplicationSceneManifest</key> <dict>     <key>UISceneConfigurations</key>     <dict>         <key>CPTemplateApplicationSceneSessionRoleApplication</key>         <array>             <dict>                 <key>UISceneClassName</key>                 <string>CPTemplateApplicationScene</string>                 <key>UISceneConfigurationName</key>                 <string>MyApp—Car</string>                 <key>UISceneDelegateClassName</key>                 <string>MyApp.CarPlaySceneDelegate</string>             </dict>         </array>     </dict> </dict>

列表模板 – CPListTemplate

在CPTemplateApplicationSceneDelegate协议的didDisconnect回调方法中,我们对模板进行初始化。当应用程序在车机屏幕上启动时,CarPlay框架将调用此didConnect方法。

可以看到,系统自动创建了CPInterfaceController实例,作为我们CarPlay应用的入口Controller,我们只需在回调中持有这个实例即可。然后我们创建了一个列表模板 CPListTemplate,其接收多组CPListSection,section中包含多个CPListItem,这是一个最基本的列表元素,有点类似tableViewCell。在这里,我们将CPListTemplate设置为应用程序的根模板。而车机断开连接时,didDisconnect回调将被调用,在里面可以做一些清理工作。

// CarPlay App Lifecycle  import CarPlay  class CarPlaySceneDelegate: UIResponder, CPTemplateApplicationSceneDelegate {     var interfaceController: CPInterfaceController?      func templateApplicationScene(_ templateApplicationScene: CPTemplateApplicationScene,             didConnect interfaceController: CPInterfaceController) {          self.interfaceController = interfaceController         let item = CPListItem(text: "Rubber Soul", detailText: "The Beatles")          let section = CPListSection(items: [item])          let listTemplate = CPListTemplate(title: "Albums", sections: [section])         interfaceController.setRootTemplate(listTemplate, animated: true)     }    func templateApplicationScene(_ templateApplicationScene: CPTemplateApplicationScene,             didDisconnect interfaceController: CPInterfaceController) {     self.interfaceController = nil }

WWDC20 10635 - 使用CarPlay车载系统为你的App提速

CPListItem代表列表模板中的一行,我们可以设置其被点击回调,该回调接收两个参数,一个是当前所点击的item对象,另一个是completion block。我们可以在点击回调处理一些耗时操作,carplay在没有接收到completion()的调用之前,会在界面上显示loading,让用户知道应用程序正忙。

// CPListTemplate  import CarPlay  let item = CPListItem(text: "Rubber Soul", detailText: "The Beatles")  item.listItemHandler = { item, completion, [weak self] in     // Start playback, then...     self?.interfaceController.pushTemplate(CPNowPlayingTemplate.shared, animated: true)     completion() }  // Later... item.image = ...

同时,在iOS14中,CPListItem中原有很多只读的属性,现在也可以自由赋值了,比如detailText、image、accessoryImage等。

标签栏模板 – tab bar template

WWDC20 10635 - 使用CarPlay车载系统为你的App提速

这是一种新的容器模板,相当于CarPlay中的TabbarController。可以作为其他模板的父容器,创建方式也很简单。

// CPTabBarTemplate  import CarPlay  let item = CPListItem(text: "Rubber Soul", detailText: "The Beatles")  let section = CPListSection(items: [item])  let favorites = CPListTemplate(title: "Albums", sections: [section]) favorites.tabSystemItem = .favorites favorites.showsTabBadge = true  let albums: CPGridTemplate = ... albums.tabTitle = "Albums" albums.tabImage = ...  let tabBarTemplate = CPTabBarTemplate(templates: [favorites, albums]) self.interfaceController.setRootTemplate(tabBarTemplate, animated: false)  // Later... favorites.showsTabBadge = false tabBarTemplate.updateTemplates([favorites, albums])

在这段实例代码中,我们创建了一个CPListTemplate和一个CPGridTemplate,作为CPTabBarTemplate的子模板。在iOS 14中,每个CarPlay模板都继承了一些新属性,自定义该模板变得更加灵活。比如我们可以设置tabber的标题,选择系统提供的icon或提供自己的自定义icon。

CPListImageRowItem

WWDC20 10635 - 使用CarPlay车载系统为你的App提速
CPListImageRowItem,在CPListItem的基础上,增加了对图片展示的支持。我们可以用一个UIImage的列表来初始化这个item。

// List Items for Audio Apps  import CarPlay  let gridImages: [UIImage] = ... let imageRowItem = CPListImageRowItem(text: "Recent Audiobooks", images: gridImages)   imageRowItem.listItemHandler = { item, completion in     print("Selected image row header!")     completion() }  imageRowItem.listImageRowHandler = { item, index, completion in     print("Selected artwork at index (index)!")     completion() }  let section = CPListSection(items: [imageRowItem])  let listTemplate = CPListTemplate(title: "Listen Now", sections: [section])  self.interfaceController.pushTemplate(listTemplate, animated: true)

与ListItem类似,通过listImageRowHandler回调,可以接收每个图片的点击事件,回调方法执行完毕后,别忘了调用completion block。

播放器模板 – NowPlayingTemplate

WWDC20 10635 - 使用CarPlay车载系统为你的App提速

作为CarPlay音频应用中最重要的模板,nowPlayingTemplate, CarPlay用户熟悉的“正在播放”屏幕,在iOS14中作为一个全新的模板提供给开发者使用,相比以前固定的正在播放界面,nowPlayingTemplate提供了较多的自定义接口。

  • 自定义“正在播放下一个”按钮和“相册艺术家”按钮。
  • 自定义播放控制按钮。

要注意的是,nowPlayingTemplate是一个单例。并且,如果启用了可选的“ Playing Next”和“ Artist”按钮,则应该为这些按钮操作至少添加一个观察者。

在应用程序在CarPlay中启动后,我们需要尽快初始化nowPlayingTemplate并设置属性,因为系统可能随时会显示这个界面。例如,当用户点击CarPlay主屏幕上的“正在播放”按钮时,系统将启动我们的应用并立即显示nowPlayingTemplate。当我们应用成为“正在播放”应用时,系统还会将“正在播放”栏按钮添加到CarPlay的应用导航栏中。如果用户点击该按钮,系统也会显示我们的nowPlayingTemplate。

如果其他应用成为“正在播放”应用,则系统将自动从CarPlay的导航栏或标签栏中删除“正在播放”栏按钮。

最后,只能将列表模板压入模板栈中的nowPlayingTemplate的顶部。比如点击“正在播放下一个”按钮,最好push一个列表模板,来展示用户的播放列表。

在这段代码中,我们在didConnect回调中,初始化nowPlayingTemplate单例,并添加一个控制播放速度的按钮,并添加监听事件。

“`swift
// Now Playing Template

概述

CarPlay 作为iOS功能在汽车上的延伸,又被称作“车载iOS”。自2013年苹果在WWDC上介绍CarPlay以来,支持CarPlay的汽车品牌越来越多,在汽车中控台上使用QQ音乐和豆瓣电台不再是一件麻烦事。

从iOS12开始,CarPlay开发API被首次引入,开始支持第三方导航,如百度地图、Waze、Google Maps、高德地图,让习惯iOS设备的车主不再只有安卓系统车机一种选择了。

基于模板(template)

CarPlay作为一个车载系统,有一点和普通iOS App开发有很大不同。所有的CarPlay API都基于Apple预先设定好的“模板”,开发者不能像构建普通手机App那样自定义UI和功能。原因也很简单,车载系统是给汽车驾驶员而非乘客使用的,驾驶安全性必然是重中之重,使用预设的模板,能最大限度地限制开发者构建对驾驶员有任何打扰的功能,让应用严格按照苹果设定的流程来运行。当然,CarPlay目前提供了几种类型的模板对象,也可以构建出色的CarPlay应用。

新特性

iOS14中,CarPlay框架提供了一组全新的模板,并对现有模板进行了改进。

WWDC20 10635 - 使用CarPlay车载系统为你的App提速

  • 用于音频应用的新控件和新模板。

  • 用于即时通信应用的新控件。

  • 用于充电桩和停车应用的新模板。

  • 用于快餐订购的新模板。

音频应用

iOS14 引入了一些用于音频应用程序的新模板。通过这些新的音频模板,iOS14中的车载音频应用将会有更丰富的用户体验。在以前的版本中,构建CarPlay音频应用程序需要用到 playable content API。 在iOS 14中,该API将被弃用,而使用新引入的”音频模板”。

WWDC20 10635 - 使用CarPlay车载系统为你的App提速

重要原则

首先,我们回顾一下在CarPlay中构建应用程序时应牢记的一些设计原则。

  • 为驾驶员设计
  • 流线型交互
  • 复用App配置
  • 首先在CarPlay中启动

CarPlay是为驾驶员而非乘客而设计的。 应用程序需要从最常见的场景启动,并让每个交互操作简化成可以在几秒内完成的任务。同时,要尽可能复用主App中的各种配置,以最小化CarPlay场景下用户需要进行的任何操作。应用程序可能会首先在CarPlay中启动,并且只能在CarPlay中启动。当用户在CarPlay主屏幕上点击您的应用程序时,应用程序将连接到汽车场景,而不是iPhone场景。因此,消除应用程序中依赖于iPhone上启动的任何逻辑非常重要。

iOS13中,苹果引入了UIScene的概念,用于构建多窗口应用。在车载场景下,车机屏幕属于一个新的窗口,

使用UIScene可以轻松做到这一点。实际上,CarPlay应用必须采用UIScene才能使用CarPlay框架,因此必须从传统的UIWindow和UIApplicationDelegate API向UIScene过渡。

前面提到,iOS14以前,CarPlay构建音频应用程序,使用Playable content API来实现,系统使用音频元数据(如专辑和歌曲),来组装好播放器UI。如果你的应用还将支持iOS13,那么Playable content API和新的模板将同时存在。在iOS 13及更低版本上,系统将启动Playable content API的应用。在iOS14中,则使用音频模板。

在示例场景中,我们需要采用UIScene才能使用CarPlay模板。首先需要在Info.plist中声明一个scene。

// CarPlay Scene Manifest  <key>UIApplicationSceneManifest</key> <dict>     <key>UISceneConfigurations</key>     <dict>         <key>CPTemplateApplicationSceneSessionRoleApplication</key>         <array>             <dict>                 <key>UISceneClassName</key>                 <string>CPTemplateApplicationScene</string>                 <key>UISceneConfigurationName</key>                 <string>MyApp—Car</string>                 <key>UISceneDelegateClassName</key>                 <string>MyApp.CarPlaySceneDelegate</string>             </dict>         </array>     </dict> </dict>

列表模板 – CPListTemplate

在CPTemplateApplicationSceneDelegate协议的didDisconnect回调方法中,我们对模板进行初始化。当应用程序在车机屏幕上启动时,CarPlay框架将调用此didConnect方法。

可以看到,系统自动创建了CPInterfaceController实例,作为我们CarPlay应用的入口Controller,我们只需在回调中持有这个实例即可。然后我们创建了一个列表模板 CPListTemplate,其接收多组CPListSection,section中包含多个CPListItem,这是一个最基本的列表元素,有点类似tableViewCell。在这里,我们将CPListTemplate设置为应用程序的根模板。而车机断开连接时,didDisconnect回调将被调用,在里面可以做一些清理工作。

// CarPlay App Lifecycle  import CarPlay  class CarPlaySceneDelegate: UIResponder, CPTemplateApplicationSceneDelegate {     var interfaceController: CPInterfaceController?      func templateApplicationScene(_ templateApplicationScene: CPTemplateApplicationScene,             didConnect interfaceController: CPInterfaceController) {          self.interfaceController = interfaceController         let item = CPListItem(text: "Rubber Soul", detailText: "The Beatles")          let section = CPListSection(items: [item])          let listTemplate = CPListTemplate(title: "Albums", sections: [section])         interfaceController.setRootTemplate(listTemplate, animated: true)     }    func templateApplicationScene(_ templateApplicationScene: CPTemplateApplicationScene,             didDisconnect interfaceController: CPInterfaceController) {     self.interfaceController = nil }

WWDC20 10635 - 使用CarPlay车载系统为你的App提速

CPListItem代表列表模板中的一行,我们可以设置其被点击回调,该回调接收两个参数,一个是当前所点击的item对象,另一个是completion block。我们可以在点击回调处理一些耗时操作,carplay在没有接收到completion()的调用之前,会在界面上显示loading,让用户知道应用程序正忙。

// CPListTemplate  import CarPlay  let item = CPListItem(text: "Rubber Soul", detailText: "The Beatles")  item.listItemHandler = { item, completion, [weak self] in     // Start playback, then...     self?.interfaceController.pushTemplate(CPNowPlayingTemplate.shared, animated: true)     completion() }  // Later... item.image = ...

同时,在iOS14中,CPListItem中原有很多只读的属性,现在也可以自由赋值了,比如detailText、image、accessoryImage等。

标签栏模板 – tab bar template

WWDC20 10635 - 使用CarPlay车载系统为你的App提速

这是一种新的容器模板,相当于CarPlay中的TabbarController。可以作为其他模板的父容器,创建方式也很简单。

// CPTabBarTemplate  import CarPlay  let item = CPListItem(text: "Rubber Soul", detailText: "The Beatles")  let section = CPListSection(items: [item])  let favorites = CPListTemplate(title: "Albums", sections: [section]) favorites.tabSystemItem = .favorites favorites.showsTabBadge = true  let albums: CPGridTemplate = ... albums.tabTitle = "Albums" albums.tabImage = ...  let tabBarTemplate = CPTabBarTemplate(templates: [favorites, albums]) self.interfaceController.setRootTemplate(tabBarTemplate, animated: false)  // Later... favorites.showsTabBadge = false tabBarTemplate.updateTemplates([favorites, albums])

在这段实例代码中,我们创建了一个CPListTemplate和一个CPGridTemplate,作为CPTabBarTemplate的子模板。在iOS 14中,每个CarPlay模板都继承了一些新属性,自定义该模板变得更加灵活。比如我们可以设置tabber的标题,选择系统提供的icon或提供自己的自定义icon。

CPListImageRowItem

WWDC20 10635 - 使用CarPlay车载系统为你的App提速
CPListImageRowItem,在CPListItem的基础上,增加了对图片展示的支持。我们可以用一个UIImage的列表来初始化这个item。

// List Items for Audio Apps  import CarPlay  let gridImages: [UIImage] = ... let imageRowItem = CPListImageRowItem(text: "Recent Audiobooks", images: gridImages)   imageRowItem.listItemHandler = { item, completion in     print("Selected image row header!")     completion() }  imageRowItem.listImageRowHandler = { item, index, completion in     print("Selected artwork at index (index)!")     completion() }  let section = CPListSection(items: [imageRowItem])  let listTemplate = CPListTemplate(title: "Listen Now", sections: [section])  self.interfaceController.pushTemplate(listTemplate, animated: true)

与ListItem类似,通过listImageRowHandler回调,可以接收每个图片的点击事件,回调方法执行完毕后,别忘了调用completion block。

播放器模板 – NowPlayingTemplate

WWDC20 10635 - 使用CarPlay车载系统为你的App提速

作为CarPlay音频应用中最重要的模板,nowPlayingTemplate, CarPlay用户熟悉的“正在播放”屏幕,在iOS14中作为一个全新的模板提供给开发者使用,相比以前固定的正在播放界面,nowPlayingTemplate提供了较多的自定义接口。

  • 自定义“正在播放下一个”按钮和“相册艺术家”按钮。
  • 自定义播放控制按钮。

要注意的是,nowPlayingTemplate是一个单例。并且,如果启用了可选的“ Playing Next”和“ Artist”按钮,则应该为这些按钮操作至少添加一个观察者。

在应用程序在CarPlay中启动后,我们需要尽快初始化nowPlayingTemplate并设置属性,因为系统可能随时会显示这个界面。例如,当用户点击CarPlay主屏幕上的“正在播放”按钮时,系统将启动我们的应用并立即显示nowPlayingTemplate。当我们应用成为“正在播放”应用时,系统还会将“正在播放”栏按钮添加到CarPlay的应用导航栏中。如果用户点击该按钮,系统也会显示我们的nowPlayingTemplate。

如果其他应用成为“正在播放”应用,则系统将自动从CarPlay的导航栏或标签栏中删除“正在播放”栏按钮。

最后,只能将列表模板压入模板栈中的nowPlayingTemplate的顶部。比如点击“正在播放下一个”按钮,最好push一个列表模板,来展示用户的播放列表。

在这段代码中,我们在didConnect回调中,初始化nowPlayingTemplate单例,并添加一个控制播放速度的按钮,并添加监听事件。

“`swift
// Now Playing Template

概述

CarPlay 作为iOS功能在汽车上的延伸,又被称作“车载iOS”。自2013年苹果在WWDC上介绍CarPlay以来,支持CarPlay的汽车品牌越来越多,在汽车中控台上使用QQ音乐和豆瓣电台不再是一件麻烦事。

从iOS12开始,CarPlay开发API被首次引入,开始支持第三方导航,如百度地图、Waze、Google Maps、高德地图,让习惯iOS设备的车主不再只有安卓系统车机一种选择了。

基于模板(template)

CarPlay作为一个车载系统,有一点和普通iOS App开发有很大不同。所有的CarPlay API都基于Apple预先设定好的“模板”,开发者不能像构建普通手机App那样自定义UI和功能。原因也很简单,车载系统是给汽车驾驶员而非乘客使用的,驾驶安全性必然是重中之重,使用预设的模板,能最大限度地限制开发者构建对驾驶员有任何打扰的功能,让应用严格按照苹果设定的流程来运行。当然,CarPlay目前提供了几种类型的模板对象,也可以构建出色的CarPlay应用。

新特性

iOS14中,CarPlay框架提供了一组全新的模板,并对现有模板进行了改进。

WWDC20 10635 - 使用CarPlay车载系统为你的App提速

  • 用于音频应用的新控件和新模板。

  • 用于即时通信应用的新控件。

  • 用于充电桩和停车应用的新模板。

  • 用于快餐订购的新模板。

音频应用

iOS14 引入了一些用于音频应用程序的新模板。通过这些新的音频模板,iOS14中的车载音频应用将会有更丰富的用户体验。在以前的版本中,构建CarPlay音频应用程序需要用到 playable content API。 在iOS 14中,该API将被弃用,而使用新引入的”音频模板”。

WWDC20 10635 - 使用CarPlay车载系统为你的App提速

重要原则

首先,我们回顾一下在CarPlay中构建应用程序时应牢记的一些设计原则。

  • 为驾驶员设计
  • 流线型交互
  • 复用App配置
  • 首先在CarPlay中启动

CarPlay是为驾驶员而非乘客而设计的。 应用程序需要从最常见的场景启动,并让每个交互操作简化成可以在几秒内完成的任务。同时,要尽可能复用主App中的各种配置,以最小化CarPlay场景下用户需要进行的任何操作。应用程序可能会首先在CarPlay中启动,并且只能在CarPlay中启动。当用户在CarPlay主屏幕上点击您的应用程序时,应用程序将连接到汽车场景,而不是iPhone场景。因此,消除应用程序中依赖于iPhone上启动的任何逻辑非常重要。

iOS13中,苹果引入了UIScene的概念,用于构建多窗口应用。在车载场景下,车机屏幕属于一个新的窗口,

使用UIScene可以轻松做到这一点。实际上,CarPlay应用必须采用UIScene才能使用CarPlay框架,因此必须从传统的UIWindow和UIApplicationDelegate API向UIScene过渡。

前面提到,iOS14以前,CarPlay构建音频应用程序,使用Playable content API来实现,系统使用音频元数据(如专辑和歌曲),来组装好播放器UI。如果你的应用还将支持iOS13,那么Playable content API和新的模板将同时存在。在iOS 13及更低版本上,系统将启动Playable content API的应用。在iOS14中,则使用音频模板。

在示例场景中,我们需要采用UIScene才能使用CarPlay模板。首先需要在Info.plist中声明一个scene。

// CarPlay Scene Manifest  <key>UIApplicationSceneManifest</key> <dict>     <key>UISceneConfigurations</key>     <dict>         <key>CPTemplateApplicationSceneSessionRoleApplication</key>         <array>             <dict>                 <key>UISceneClassName</key>                 <string>CPTemplateApplicationScene</string>                 <key>UISceneConfigurationName</key>                 <string>MyApp—Car</string>                 <key>UISceneDelegateClassName</key>                 <string>MyApp.CarPlaySceneDelegate</string>             </dict>         </array>     </dict> </dict>

列表模板 – CPListTemplate

在CPTemplateApplicationSceneDelegate协议的didDisconnect回调方法中,我们对模板进行初始化。当应用程序在车机屏幕上启动时,CarPlay框架将调用此didConnect方法。

可以看到,系统自动创建了CPInterfaceController实例,作为我们CarPlay应用的入口Controller,我们只需在回调中持有这个实例即可。然后我们创建了一个列表模板 CPListTemplate,其接收多组CPListSection,section中包含多个CPListItem,这是一个最基本的列表元素,有点类似tableViewCell。在这里,我们将CPListTemplate设置为应用程序的根模板。而车机断开连接时,didDisconnect回调将被调用,在里面可以做一些清理工作。

// CarPlay App Lifecycle  import CarPlay  class CarPlaySceneDelegate: UIResponder, CPTemplateApplicationSceneDelegate {     var interfaceController: CPInterfaceController?      func templateApplicationScene(_ templateApplicationScene: CPTemplateApplicationScene,             didConnect interfaceController: CPInterfaceController) {          self.interfaceController = interfaceController         let item = CPListItem(text: "Rubber Soul", detailText: "The Beatles")          let section = CPListSection(items: [item])          let listTemplate = CPListTemplate(title: "Albums", sections: [section])         interfaceController.setRootTemplate(listTemplate, animated: true)     }    func templateApplicationScene(_ templateApplicationScene: CPTemplateApplicationScene,             didDisconnect interfaceController: CPInterfaceController) {     self.interfaceController = nil }

WWDC20 10635 - 使用CarPlay车载系统为你的App提速

CPListItem代表列表模板中的一行,我们可以设置其被点击回调,该回调接收两个参数,一个是当前所点击的item对象,另一个是completion block。我们可以在点击回调处理一些耗时操作,carplay在没有接收到completion()的调用之前,会在界面上显示loading,让用户知道应用程序正忙。

// CPListTemplate  import CarPlay  let item = CPListItem(text: "Rubber Soul", detailText: "The Beatles")  item.listItemHandler = { item, completion, [weak self] in     // Start playback, then...     self?.interfaceController.pushTemplate(CPNowPlayingTemplate.shared, animated: true)     completion() }  // Later... item.image = ...

同时,在iOS14中,CPListItem中原有很多只读的属性,现在也可以自由赋值了,比如detailText、image、accessoryImage等。

标签栏模板 – tab bar template

WWDC20 10635 - 使用CarPlay车载系统为你的App提速

这是一种新的容器模板,相当于CarPlay中的TabbarController。可以作为其他模板的父容器,创建方式也很简单。

// CPTabBarTemplate  import CarPlay  let item = CPListItem(text: "Rubber Soul", detailText: "The Beatles")  let section = CPListSection(items: [item])  let favorites = CPListTemplate(title: "Albums", sections: [section]) favorites.tabSystemItem = .favorites favorites.showsTabBadge = true  let albums: CPGridTemplate = ... albums.tabTitle = "Albums" albums.tabImage = ...  let tabBarTemplate = CPTabBarTemplate(templates: [favorites, albums]) self.interfaceController.setRootTemplate(tabBarTemplate, animated: false)  // Later... favorites.showsTabBadge = false tabBarTemplate.updateTemplates([favorites, albums])

在这段实例代码中,我们创建了一个CPListTemplate和一个CPGridTemplate,作为CPTabBarTemplate的子模板。在iOS 14中,每个CarPlay模板都继承了一些新属性,自定义该模板变得更加灵活。比如我们可以设置tabber的标题,选择系统提供的icon或提供自己的自定义icon。

CPListImageRowItem

WWDC20 10635 - 使用CarPlay车载系统为你的App提速
CPListImageRowItem,在CPListItem的基础上,增加了对图片展示的支持。我们可以用一个UIImage的列表来初始化这个item。

// List Items for Audio Apps  import CarPlay  let gridImages: [UIImage] = ... let imageRowItem = CPListImageRowItem(text: "Recent Audiobooks", images: gridImages)   imageRowItem.listItemHandler = { item, completion in     print("Selected image row header!")     completion() }  imageRowItem.listImageRowHandler = { item, index, completion in     print("Selected artwork at index (index)!")     completion() }  let section = CPListSection(items: [imageRowItem])  let listTemplate = CPListTemplate(title: "Listen Now", sections: [section])  self.interfaceController.pushTemplate(listTemplate, animated: true)

与ListItem类似,通过listImageRowHandler回调,可以接收每个图片的点击事件,回调方法执行完毕后,别忘了调用completion block。

播放器模板 – NowPlayingTemplate

WWDC20 10635 - 使用CarPlay车载系统为你的App提速

作为CarPlay音频应用中最重要的模板,nowPlayingTemplate, CarPlay用户熟悉的“正在播放”屏幕,在iOS14中作为一个全新的模板提供给开发者使用,相比以前固定的正在播放界面,nowPlayingTemplate提供了较多的自定义接口。

  • 自定义“正在播放下一个”按钮和“相册艺术家”按钮。
  • 自定义播放控制按钮。

要注意的是,nowPlayingTemplate是一个单例。并且,如果启用了可选的“ Playing Next”和“ Artist”按钮,则应该为这些按钮操作至少添加一个观察者。

在应用程序在CarPlay中启动后,我们需要尽快初始化nowPlayingTemplate并设置属性,因为系统可能随时会显示这个界面。例如,当用户点击CarPlay主屏幕上的“正在播放”按钮时,系统将启动我们的应用并立即显示nowPlayingTemplate。当我们应用成为“正在播放”应用时,系统还会将“正在播放”栏按钮添加到CarPlay的应用导航栏中。如果用户点击该按钮,系统也会显示我们的nowPlayingTemplate。

如果其他应用成为“正在播放”应用,则系统将自动从CarPlay的导航栏或标签栏中删除“正在播放”栏按钮。

最后,只能将列表模板压入模板栈中的nowPlayingTemplate的顶部。比如点击“正在播放下一个”按钮,最好push一个列表模板,来展示用户的播放列表。

在这段代码中,我们在didConnect回调中,初始化nowPlayingTemplate单例,并添加一个控制播放速度的按钮,并添加监听事件。

“`swift
// Now Playing Template

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » WWDC20 10635 – 使用CarPlay车载系统为你的App提速求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们