TVTopShelfContentProvider and Swift 6 Concurrency

I have a TVTopShelfContentProvider that implements

func loadTopShelfContent() async -> (any TVTopShelfContent)?

When running on Xcode 26 b5 I am seeing the following error in swift 6 mode.

Non-Sendable type '(any TVTopShelfContent)?' cannot be returned from nonisolated override to caller of superclass instance method 'loadTopShelfContent()'

I'm not sure exactly what's changed here as it used to compile just fine but it's unclear now how I can work-around this error or how the API is supposed to be used.

The following definition is enough to trigger the error in Swift 6 language mode.

import TVServices

class ContentProvider: TVTopShelfContentProvider {
  override func loadTopShelfContent() async -> (any TVTopShelfContent)? {
    return nil
  }
}

I can "fix" it by adding @preconcurrency to the TVServices import but it seems like this API is unusable currently? Or maybe it's user error on my part?

Answered by DTS Engineer in 853303022

I’m gonna recommend that you file a bug about this.

There are two factors in play here:

  • You’re overriding a method from your super class.
  • You’re choosing to override the async variant rather than the completion handler variant.

That combination is tricky, and I don’t fully understand how those two things fit together. However, you’re not doing anything wrong here, and hence my recommendation to file a bug.

Please post your bug number, just for the record

In terms of a workaround, I see two options:

  • The @preconcurrency import you’ve already uncovered.
  • Instead of overriding the async variant, override the completion handler variant. So:
class MyContentProvider: TVTopShelfContentProvider {

    override func loadTopShelfContent(completionHandler: @escaping ((any TVTopShelfContent)?) -> Void) {
        let content = TVTopShelfCarouselContent(style: .actions, items: [])
        completionHandler(content)
    }
}

Both of these should work. I’m not confident enough of my understanding here to strongly recommend one over the other, but if I were in your shoes I’d probably pick the second one. That’s because the @preconcurrency import has a wider scope of impact. However, you might find that you need the @preconcurrency import for some other issue anyway.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I’m gonna recommend that you file a bug about this.

There are two factors in play here:

  • You’re overriding a method from your super class.
  • You’re choosing to override the async variant rather than the completion handler variant.

That combination is tricky, and I don’t fully understand how those two things fit together. However, you’re not doing anything wrong here, and hence my recommendation to file a bug.

Please post your bug number, just for the record

In terms of a workaround, I see two options:

  • The @preconcurrency import you’ve already uncovered.
  • Instead of overriding the async variant, override the completion handler variant. So:
class MyContentProvider: TVTopShelfContentProvider {

    override func loadTopShelfContent(completionHandler: @escaping ((any TVTopShelfContent)?) -> Void) {
        let content = TVTopShelfCarouselContent(style: .actions, items: [])
        completionHandler(content)
    }
}

Both of these should work. I’m not confident enough of my understanding here to strongly recommend one over the other, but if I were in your shoes I’d probably pick the second one. That’s because the @preconcurrency import has a wider scope of impact. However, you might find that you need the @preconcurrency import for some other issue anyway.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks for the confirmation.

Unfortunately the ergonomics of the completion hander version are a little awkward for my use case because of other asynchronous logic and concurrency calls. I will use @preconncurrency for now and hope that the API issues can get resolved soon.

I have filed this as: FB19576198

(no idea where I was supposed to file this as I couldn't find an option for TVServices so I set it as "‌Something else not on this list" but hopefully it makes it to the right people!)

TVTopShelfContentProvider and Swift 6 Concurrency
 
 
Q