在 CarPlay 应用程序中显示加载 Activity 指示器,如 Apple 文档所述

Show loading Activity Indicator in CarPlay app as Apple's docs state you should

根据 Apple's Documentation one should show an Activity Indicator 指示某些内容正在加载或需要一些时间才能在屏幕上显示。这是合理的,我很乐意这样做...

我觉得我遗漏了一些明显的东西,但我无法弄清楚如何在 CarPlay 应用程序的模板中显示 activity 指示器,因为我无权访问该视图。我只能与可用的模板进行交互。

如果我试图匹配 Apple 文档中的图像,我会假设我需要使用 listTemplate 以及如何向其添加 activity 指示符。

还有其他人遇到过这个吗?如有任何帮助,我们将不胜感激!


WWDC 期间 Apple 工程师的更新 (7/2021)

我在 WWDC21 期间问了这个问题,得到了以下回复。

如果您正在使用 CPListTemplate,系统将在用户点击列表项时调用您的 -[CPListItem handler]。系统为您的处理程序提供了一个完成块,您应该确保在您的应用程序完成处理用户的选择后调用它。如果您的应用程序没有立即调用完成块,那也没关系!也许您的应用需要执行需要一些时间的网络请求。如果尚未调用完成块,系统将在短暂延迟后自动将微调器添加到您的列表项。

另一种选择是使用单个列表项显示列表模板,该列表项指示其余项仍然 loading/in-progress。

特别是对于选项卡栏模板,您可以更新已显示的选项卡。例如,如果绝对不能在应用程序启动时立即显示一个或多个选项卡,您可以动态添加它们。

或者,对于全屏演示,您可以显示 CPAlertTemplate 以指示应用中的错误或加载状态。

我遇到了与您相同的问题 - 我无法找到如何在从 API 异步加载内容时显示加载微调器。 Apple Docs 在试图解决这个问题上不是很有帮助。经过大量测试,特别是在车内的真实 CarPlay 设备上,我找到了答案。

对我来说,当在 MPPlayableContentDataSource 的 beginLoadingChildItems() 中请求数据时,如果我在几秒钟内没有调用 beginLoadingChildItems() 的完成处理程序,CarPlay 屏幕上就会显示加载微调器。所以 beginLoadingChildItems() 由 CarPlay 调用,我发出一个 API 请求,只有当请求 returns 数据(或失败)时,我才调用 beginLoadingChildItems() 的完成处理程序。大多数时候 API 请求 returns 非常快,加载微调器不显示。但是当 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 来获取数据:

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 屏幕上显示加载微调器。

非常感谢@Xeaza 用 Apple 工程师的回答更新问题。

如此处所述,如果您使用的是 CPListTemplate,则可以在列表项中显示 activity 指示符。或者更确切地说,CarPlay 会为您做到这一点。

缺少一件重要的东西,我花了一段时间才找到:

仅当所选列表项的 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()
    }
}