Active Filters: tvOS


#188: Adding a Top Shelf Extension to a tvOS App 🍸📺


One of the best parts of tvOS is the Top Shelf. It's the bit just above the top row of apps on the home screen that shows previews of each app's content when it's focused (think "Trending Videos", "Recent Photos", etc.).

Today we'll learn how we can provide this same type of functionality in our own apps, by adding a Top Shelf Extension. Let's get started:

We'll add a new target to our app. We'll create a new tvOS > Application Extension > TV Services Extension.

Xcode will generate a ServiceProvider class for us that conforms to the TVTopShelfProvider protocol and provides TVContentItems back to the system.

We'll use .Sectioned for our style so we can provide items like this:

The .Inline style is neat too, but its purpose is only for displaying wide banners like the App Store app.

We'll create a single section item, then set its topShelfItems to an array of items for the things we actually want to display.

var topShelfItems: [TVContentItem] { // ...
  shipsSection.title = "Recent Launches"
  shipsSection.topShelfItems = recentlyLaunchedShips()
    .map { $0.asTVContentItem(sectionID) }
  // ...

We can use TVContentItem's properties to customize/enhance its behavior:

item.title = name
item.imageURL = NSURL(string: "\(identifier).jpg")
item.imageShape = .HDTV
item.displayURL = NSURL(string: "spaceships://ship/\(identifier)")
item.playURL = NSURL(string: "spaceships://ship/\(identifier)")

There's actually a lot of features packed into this little class: Simple things like separate deep-link URL for selecting, or pressing the Play button on an item, or more advanced functionality like the currentPosition property, which can help us display the user's "watch progress" on our top shelf items.

Download a fully working example project here


#186: Focus Engine Basics on tvOS 📺


One of the biggest things that sets tvOS apart from iOS is the Focus Engine. Today we'll check out what it does, how it works, and how we can interact with it in our apps. Let's get started.

The Focus Engine is the part of tvOS that manages which view the user is currently focused on in tvOS's interface, as well as moving to another view when the user performs a gesture on their remote (or a game controller).

We get all of this functionality "for free", as long as we're using UIKit controls to construct the UI of our apps.

The Focus Engine will listen for a user's input like a left swipe, then it will look for views that are currently to the left on screen of the currently focused view, and move focus to them.

For many apps, that's really all there is to it. 1.) Construct our UI, 2.) Focus Engine handles it all.

For more advanced usage, there's a few places we can "hook into" and interact with the Focus Engine. Here's some examples:

  • We can update the currently focused view in a similar way to how make layout changes on iOS. First we override the preferredFocusView property on our UIViewController, then we call setNeedsFocusUpdate. (Only works if the view controller already contains the currently focused view).

  • We can have the system ask us if it's ok to make a proposed focus change. For this we'd implement shouldUpdateFocusInContent on our view controllers, answering ‘yes' or ‘no'.

  • Lastly, we can use the didUpdateFocusInContext function to (for example) animate our custom views alongside the system's animations.