tvOS 13 top shelf - NSExtensionPrincipalClass `product_module_name.ContentProvider` must implement at least one public protocol

Viewed 942

Migrating a tvOS sectioned style top shelf from using TVTopShelfProvider, now deprecated, to TVTopShelfContentProvider causes an NSException on launch.

The error, NSExtensionPrincipalClass product_module_name.ContentProvider must implement at least one public protocol suggests that my class, ContentProvider, must use a protocol. TVTopShelfContentProvider is a class and not a protocol though.

Looking at Apple's example project you can see that they also only subclass TVTopShelfContentProvider.

Minimal example:

class ContentProvider: TVTopShelfContentProvider {

    override func loadTopShelfContent(completionHandler: @escaping (TVTopShelfContent?) -> Void) {
        requestMediaItemsIfNeeded {
            let itemCollection: TVTopShelfItemCollection = TVTopShelfItemCollection(items: self.items)
            itemCollection.title = "Collection Title"

            let sectionedContent: TVTopShelfSectionedContent = TVTopShelfSectionedContent(sections: [itemCollection])
            completionHandler(sectionedContent)
        }
    }

}

Top shelf related Info.plist values:

<key>NSExtension</key>
<dict>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.tv-top-shelf</string>
    <key>NSExtensionPrincipalClass</key>
    <string>$(PRODUCT_MODULE_NAME).ContentProvider</string>
</dict>

Am I missing a project configuration value that needs to be added/updated? Created a new minimal top shelf extension and these look to be the only changes needed.

3 Answers

To migrate top-shelf image implementation to support full-screen assets should be updated 2 things:

  1. Update Info.plist. Pay attention to update NSExtensionPointIdentifier

Info.plist

  1. Update productType to "com.apple.product-type.app-extension" I could not find this setting in Xcode, so I opened the project in a text editor and searched for productType

I was able to resolve this by deleting the Top Shelf extension target, configuration, and build scheme. I then recreated the Top Shelf extension target.

This is obviously an extreme solution. Unfortunately, it's still not clear what the exact issue is. I suspect Apple is doing some "magic" behind the scenes when a new Top Shelf extension is created and added to a parent target. Looking at the diff does not expose any of the possible issues.

I've been working with an outdated Apple code example and found this exact same error. I've manage to solved it by modifying the productType in the pbx project file itself, and modifying the Info.plist NSExtension attribute. (As indicated by https://stackoverflow.com/a/64882526/721929)

You can see the most significant changes in commits product type changed from tv-app-extension to app-extension https://github.com/kikeenrique/UIKitCatalogtvOSCreatingandCustomizingUIKitControls/commit/281468790fd552a6490d90f7b958eeb67ad6a70e

and

https://github.com/kikeenrique/UIKitCatalogtvOSCreatingandCustomizingUIKitControls/commit/86dfb706083078ff94b61812f6168def6bb78e52

I've also published the repository if anyone finds it of interest:

UIKit Catalog tvOS Creating and Customizing UIKit Controls

Related