在 CarPlay 应用程序中显示加载活动指示器,如 Apple 文档所述,您应该
Posted
技术标签:
【中文标题】在 CarPlay 应用程序中显示加载活动指示器,如 Apple 文档所述,您应该【英文标题】:Show loading Activity Indicator in CarPlay app as Apple's docs state you should 【发布时间】:2021-04-26 20:21:41 【问题描述】:根据Apple's Documentation,应该显示Activity Indicator,以表明某些内容正在加载或需要一些时间才能在屏幕上显示。这是合理的,我很乐意这样做...
我觉得我遗漏了一些明显的东西,但我无法弄清楚如何在 CarPlay 应用程序的模板中显示活动指示器,因为我无权访问该视图。我只能与可用的模板进行交互。
如果我试图匹配 Apple 文档中的图像,我会假设我需要使用 listTemplate
以及一些如何添加活动指示器的方法。
还有其他人遇到过这个吗?任何帮助将不胜感激!
在 WWDC (7/2021) 期间来自 Apple 工程师的更新
我在 WWDC21 期间问了这个问题,得到了以下回复。
如果您使用CPListTemplate
,当用户点击列表项时,系统将调用您的-[CPListItem handler]
。系统为您的处理程序提供了一个完成块,您应该确保在您的应用程序完成处理用户的选择后调用它。如果您的应用程序没有立即调用完成块,那没关系!也许您的应用需要执行需要一些时间的网络请求。如果尚未调用完成块,系统将在短暂延迟后自动将微调器添加到您的列表项。
另一种选择可能是显示一个带有单个列表项的列表模板,该列表项指示其余项仍在加载/正在进行中。
特别是对于标签栏模板,您可以更新已显示的标签。例如,如果绝对不能在应用启动时立即显示它们,您可以动态添加一个或多个选项卡。
或者,对于全屏演示,您可以提供 CPAlertTemplate
以指示应用中的错误或加载状态。
【问题讨论】:
也很好奇!找到解决办法了吗? 还没有...不过我一定会更新的! 【参考方案1】:我遇到了与您相同的问题 - 从 API 异步加载内容时,我找不到如何显示加载微调器。 Apple Docs 在试图解决这个问题时并没有多大帮助。经过大量测试,尤其是在汽车中的真实 CarPlay 设备上进行测试后,我有了答案。
对我来说,当在 MPPlayableContentDataSource 的 beginLoadingChildItems() 中请求数据时,如果我几秒钟内没有调用 beginLoadingChildItems() 的完成处理程序,那么 CarPlay 屏幕上会显示一个加载微调器。因此,CarPlay 调用 beginLoadingChildItems(),我发出 API 请求,只有当请求返回数据(或失败)时,我才调用 beginLoadingChildItems() 的完成处理程序。大多数情况下,API 请求会很快返回并且加载微调器不会显示。但是当 API 速度很慢时(由于连接不稳定导致几秒钟),加载微调器会显示。
我的 MPPlayableContentDataSource beginLoadingChildItems() 看起来像:
class CarPlayContentManager: NSObject, MPPlayableContentDataSource
private let contentProvider = ContentProvider()
func beginLoadingChildItems(at indexPath: IndexPath, completionHandler: @escaping (Error?) -> Void)
// Make a request to fetch data from the API, passing in completionHandler
contentProvider.fetchContentItems(completionHandler: completionHandler)
ContentProvider 只是一个获取数据的辅助类:
class ContentProvider
func fetchContentItems(completionHandler: @escaping (Error?) -> Void)
// Make the async API request
// When the API request returns (either as success or error) call completionHandler(nil)
注意:您可以通过在 beginLoadingChildItems() 中设置延迟来测试加载微调器。调用 beginLoadingChildItems() 时,只需设置 5 秒的延迟,然后在 5 秒结束后调用 completionHandler(nil)。这应该会在 CarPlay 屏幕上显示加载微调器。
【讨论】:
这就是答案!你发现的内容与我从 Apple 那里听到的内容相符。The system will automatically add a spinner to your list item after a short delay if the completion block has not yet been called.
【参考方案2】:
非常感谢 @Xeaza 用 Apple 工程师的回答更新问题。
就像那里提到的,如果您使用 CPListTemplate,您可以在列表项中显示活动指示器。或者更确切地说,CarPlay 会为您做到这一点。
遗漏了一件重要的事情,我花了一段时间才发现:
这仅在所选 listItem 的 accessoryType
设置为 .none
时才有效
如果您事先将所有项目中的accessoryType
设置为.none
,那就没问题了。如果您将其设置为.disclosureIndicator
或.cloud
,则需要在开始工作之前将其设置为.none
(处理程序中的第一行)。
let listItem = CPListItem(text: "Item Name", detailText: nil, image: UIImage(named: "yourImage")!, accessoryImage: nil, accessoryType: .disclosureIndicator)
listItem.handler = [weak self] selectableListItem, completion in
listItem.accessoryType = .none
yourFunctionThatTakesSomeTime() [weak self] (_, _) -> Void in
// do your thing
completion()
【讨论】:
以上是关于在 CarPlay 应用程序中显示加载活动指示器,如 Apple 文档所述,您应该的主要内容,如果未能解决你的问题,请参考以下文章
如何隐藏和显示加载微调器 - 活动指示器反应原生,管理道具和状态