• Open Menu Close Menu
  • Apple Developer
  • Account
  • Apple Developer
  • Discover
  • Design
  • Develop
  • Distribute
  • Support
  • Account
  • Search

More Videos

  • Overview
  • Resources
  • Transcript
  • Focus-Driven Interfaces with UIKit

    UIKit on tvOS provides the Focus Engine, which controls focus movement and handles interaction with the new Siri Remote. Find out how the Focus Engine moves focus and how you can communicate with it through the Focus API. Discover best practices for implementing focus appearance, responding to focus changes, using focus guides, debugging focus issues, and handling button presses.

    Apple TV Tech Talks - Session 3 - tvOS

    • App Programming Guide for tvOS
    • Apple TV Human Interface Guidelines
    • UIFocusEnvironment Reference
    • UIKit Catalog for tvOS (Sample Code)
      • HD Video
      • SD Video
  • So you have just seen that we put a lot of thought and effort into making this focus model work with this new interaction model.

    And the Siri remote provides us a new way of interacting with apps that allows you to sit across the room and although you can't touch the screen you still feel connected to what happening over there. Now, how much thought and effort do you have to put into your apps to make this work with you apps? This is the big question, so what is your app need to do this a part in focus model. Let's take a look.

    It's pretty straight forward. So you just need to interpret the finger movement on the remote and then based on the direction and the speed determine which view is going to be focus next. Now there is this minor thing that not everything that's visible on screen should also be focusable. So you also need to provide a way so you know which views can become focus and which other views cannot become focus. And then of course you need to move the focus and we want to do this with a nice animation of course.

    And we also must not forget that focused views should look different to unfocused ones. So we also need to provide an appearance for the currently focused one. And we want to render this tilting and parallax effect that you just saw earlier.

    And it turns out there just a couple more things that we need to take care of. OK. Of course you don't have to do that.

    So any of these things we already implemented for you so you don't have to do that in your apps and you can just take advantage of this automatically because we implemented everything in a component that we call the focus engine. For the focus engine we'll take care of all the navigation and interaction in your app and we put a lot of effort into making it feel really good with the Siri remote. But it also works with the old remote.

    So if you're having a classic Apple TV even this Siri remote works with that model as well as game controllers. And the great thing about this is that, customers don't really have to remember which app works with what controller. They just all work and they all work the same way.

    And this is the most important reason why we provide a focus engine in the first place. It provides a consisting user experience across all apps so customers instantly know how to navigate your app because it just works the way they expect it to. So in the next few minutes I like to explain a little bit more about the basics of the focus model and how the focus engine works so that you can understand how to use it and take advantage of it in your apps. It also comes with a little bit of API so we'll take a break look at that.

    And, then I also want to share some best practices with you. So, let's dive into the basics. So here is how the focus engine works.

    It all starts with standard UIKit UIview key. So just like in iOS you can this can come from a story board or you can create it programatically and of course you can mix and match those approaches. And most of the controls that, you know, from iOS are also available on tvOS.

    Now we did add something new and this is the concept of having views being able to become focused. And there is always one view in focus.

    And, then you've seen if you just move the finger on the remote a little bit the focus engine will render the parallax effect for the currently focus item automatically for you. And, then finally if you move your finger far or fast enough the focus engine will update focus to the next focusable view in the direction that you swipe. Now, this last part, let's take a closer look at how that works in detail.

    And for that let's have a look at these examples here. So we have a collection view with lots of images on screen and it's really easy to say what's in focus right now.

    The focus view in the middle appears closer to us just like we described earlier. Now for the focus engine to determine the next view to be in focus is going to look at the rectangle starting from the currently focused view extending into the direction that you swipe on the remote.

    So if we swipe right the focus engine is going to look at this rectangle. And there it will find two focusable views there to other cells in the same collection view. And, now it would move focus to the closest view and depending on how far and fast you swipe it might even go through a couple of views in that direction. Obviously this works in all four directions and it works the same way in all four directions.

    But it also works diagonally and this case if we swipe to the bottom right here the focus engine would look at this rectangle and then will determine one of those views to be called aspects. But, let's just swipe down in this example. Now you can also see that in-- focus engine is not just changing the focus it also adjusts the scrolling off set. To always make sure that the currently focused item is always fully visible. OK. So this is how the focus engine updates focus. But there is another very important thing that the focus engine takes care all for you. And for that, let's take a look at another part of the sample app.

    So here we have a collection view example and this is the button that actually brings the collection view example on screen. And, now if we push this button-let's see what happens. Now this is very simple we just bring up-- we press the button and this brings up a new view controller. So we're just presenting a new view controller. But, what happens to focus now? Now there is something that the focus engine also does at this stage and I just pause the video here it will also determine initial focus for you.

    And usually it tries to do that by setting focus geographically to the most top left view that is focusable. And in this case it's the first cell in the collection view.

    So the focus engine is not just moving the focus around it also determines the initial position of where focus should be specially if you present a new view controller. And these are the two most important concepts of how the focus engine works.

    Now, let's take a look how you app can communicate with the focus engine. And this is where the Focus API comes in.

    Now with the Focus API you can define which views in your app can actually become focus. You can also define what should be in focus initially and there is also ways for your app to figure out what's in the focus right now. So to make views focusable we've added a new method to UIView which is called canBecomeFocused. That's pretty simple the only. It only returns true or false and this what determines if this view can become focus or not. And all views and because it implemented by UIView of course all subclasses of UIView implement this.

    We've also sets sensible defaults for all the standard controls. So if you're using a button for example then the button will be focusable by default if you're using a UILabel this will not be focusable by default.

    Now you can override this in your own custom views sub classes either if you want to change the default or if you want to have you own custom views to also participate in the focus model. So this is focusable views, now how can you determine initial focus? For that will adding a new protocol to UIKit we call UIFocusEnvironment.

    Among many other things it also provides to read only property called preferredFocusView. And everything that participates in the view controller and view hierarchy implements the UIFocusEnvironment protocol. So starts with the window so all view controllers as well as all UIViews and of course their subclasses.

    They all conform to UIFocusEnvironment. And what this property does the property points to a subview in the view hierarchy that should determine initial focus.

    And, then this view could also point to another view or just point to itself. To say this is the view that should determine initial focus.

    And by creating this chain of pointing to other items in the view hierarchy we're creating what we call the preferred focus chain.

    And this is what the focus engine traverses to figure out where focus should go initially. And you can override this to guide the focus engine to the element that you want to be in focus. So this was very abstract, so let's take a look at this with another example here.

    So if we think about think back about the collection view example that I showed you is a very simple view hierarchy here.

    So we have a Window, we have Root View Controller, RootView and then we have a couple of Subviews. Now in this example, let's start with the UIWindow and by default a window points to its root view controller as a preferredFocusView. And then our example that was the UICollectionViewController.

    Now a view controller by default points to its root view as the preferredFocusView. And in our example that was the collection view.

    And then the collection view by default points to its first cell which is a UICollectionViewCell. Now in this case all the defaults got us to exactly the right view. So we didn't have to override anything. And you will see this one developing for tvOS and most cases the defaults should be fine. But if at some point if you not happy with where focus goes by default then this when you want to override the preferredFocusView property. So this is how the focus engine knows what to focus initial. Now, I want to talk briefly a little bit more about table and collection views because these are extremely useful and mostly like you'll be using them a lot in the tvOS interfaces.

    Now they also implement the UIFocusEnvironment protocols so everything I said also applies to table and collection views.

    But we've also added a few other things that make it even easier to work with those. There are now dedicated delegate methods for focus using index that have base APIs. So if you want to specify what canBecomeFocused in a table or collection view you can use delegate methods for that.

    There's table view canFocusRowAtIndexPath as well as collection view on canFocusItemAtIndexPath. And for setting the initial focus you can use the indexPathForPreferred FocusViewInTableView as well as in collection view delegates methods. Now while we're talking about table and collection views there's another little feature that we also added which can help you remember which cell was focused before.

    So sometimes you might run into a situation where you have a table view on screen. You move focus out of the table view to some other element and then you want to move it back into the table view. And by default the focus engine would just select the cell in the table view that is closest but sometimes you probably don't want that behavior and instead you want the table view to remember what was focus before and you want to go you want to have focus go back to whatever was focused before. Now you could implement that yourself using those delegate methods and it's not that hard but you can also just switch on the remembersLastFocusIndexPath property. And, then table views as well as collection views will automatically do that for you.

    OK. Let's quickly talk about how you app can find about what is in focus right now. And there was a couple of option.

    One option is to ask a specific view if its focus right now. Very simple or you can also ask UIScreen for the focusedView. And that's especially handy if you're quickly just want to reference the current focusedView specially when your debugging something and the-- in ldb. Now, note that these are read only property so you cannot set them. And you might be thinking, yeah, sometimes I want to change focus programatically but that would be a terrible idea. Just imagine how confusing it would be for the user if focus suddenly jumps to different element.

    This would completely destroy that feeling of connection and being in control of the experience. And this is why by design only the focus engine can update focus. Now that there is sometimes there are cases where it's a little bit ambiguous what should happen with focus. For example what happens if the currently focusedView is removed from the view hierarchy where should focus go then.

    Or if a new view controller is presented on top of another one or if its dismissed in control needs to go back to the previously-- to the previous one.

    Which is pretty much what happen, what happens if you use UINavigation controller and the user presses menu to go back on the spec. And, also what happens if you're using table or collection views and reload their data and all the cells are suddenly different.

    One of the cells was in focus but know everything is different. Where should focus go then? Now in all these cases the focus engine helps you out by requesting a focus update. Let's take a look at what that is in detail.

    The focus update request does nothing else than just have the focus engine determine initial focus again. So the focus engine again traverses the preferred focus chain, defines the view in the view hierarchy that should be in focused initially. And this your way to update focus to a specific view by just using the canBecomeFocused and preferredFocusView properties, over writing them and your own custom sub classes and used them to guide the focus engine to whatever view you would like to be in focus at that point in time. And this is basically how you can programatically set focus.

    Now in the unlikely case that the focus engine is not automatically requesting a focus update when you want it to, we have API for that too.

    OK so this was a very quick overview of the Focus API. And now I want to launch into a segment where I talk a little bit about five best practices that we learned about working with a lot of developers on tvOS apps. And the first thing I want to talk about is implementing focus appearance. So you've already seen that a lot of the built-in controls provide appearance for all the five possible states, especially the focus ones out of the box, will tap outs do that? It's very easy to see that here we're in on the controls tab and the focus is on the tab bar on the controls part and I can move over to view controllers, is a view controllers tab and then I can move over to those buttons and you can see those buttons also provide a default focus appearance. And then also the table view, that's; the same thing, in table views, we have those cells and the cells also provide a default focus appearance. And then of course we have collection views.

    And if you move over to the collection view where we have those gorgeous images here, and you don't set anything, you will realize that nothing happens. So what happen to this parallax effect, it seems like focus works somehow and moves correctly but what happened to this parallax effect that we would expect for those images here. Now this is because by default, collection views do not provide any appearance or focus and this is actually something that you can use to your advantage if you ever feel like the standard appearance is not exactly what you need so for example if you're using a table view, and you're not that happy with the appearance that the table view provides because you want to do it differently then that might be a good reason to move to a collection view instead.

    But most of the time, you probably want to have the default appearance. So what can you do to have those images getting this parallax effect apply? So this is also not very hard to do, you can just use-- you want image views and we added a property to UIImage view which was called adjust image when [inaudible] focus and you just have to set this to yes or true and this will instruct the focus engine to render the parallax effect for this image view whenever parent cell or view becomes focused.

    So if you put an image view into your collection view cell that would automatically apply the effect to it. Now the default is false, so you need to make sure that you enable it and all the image views that you want to get that effect and you can do this programatically of course and we also provide a way for you to do that in interphase builder. And if you do that, then this will bring this image closer to the viewer and will also render the parallax effect when people use the small movements on the remote. And it's really important that you react to subtle movements on the remote because this is one of the critical elements of the tvOS experience because this provides the sense of connectiveness to what's happening on the screen. So make sure that you always use the build in appearance effects and the parallax effect wherever you can. Sometimes, you might have more complex view hierarchies in your table or collection view cells or you have custom views and you might still be able to use the built-in effect by just flatten them, flatten those hierarchies into a single image and then still use the UIImage view and use to built-in effect and that is what we would recommend. Now if you do have your own custom controls and you can't flatten them down to a simple image, there's another way we provide for you to create your own custom effects. We also expose the subtle movement on the remote.

    To the UI motion effects, API so you can just use that to come up with your own custom effects. So this is how you can implement focus appearance.

    Now another thing that it's probably the most important thing that you will be doing and tvOS apps is you want your to apps to respond to focus changes.

    Maybe you just want to change some states in the app or maybe you want to do something small like just adding something else to the focus transition animation. And we do this a lot in our UI and you've already seen many examples here where we fade in a label when an element becomes focus and then we fade it back out when a focus moves away to another element like this.

    So here we're just switching back and forth between the first two cells in this collection view and you can see how the one label fades in while the other one fades out. Maybe you haven't seen it because that was a little bit fast.

    So let's take a look at this again in slow motion. So moving over to the other cell and the label fades in, the other label fades out and going back, the same thing happens. But there is another thing that we need to look at here, you can also swipe very quickly through a number of items.

    And the animation is the same but it's much faster, let's take a look. The focus app in animation adapts to the speed movement and this means that it rules out, if we can work with fixed animation timing here. So if that doesn't work, how can you respond to focus changes and how can you create in the effects like fading in those labels? Now I talked about UI focus environment already and we also provide a call back for you that you can use to respond to focus changes in your apps. Which is the didUpdate focus and context method.

    And you can use that every time you need to update state because focus changed in your app. But you can also use that to add animations to the same focus transition animation that we're using. And this is because we give you access to two very important objects here.

    The first one is the UI focus update context and this focus update context tells you all about how focus moves for this focus transition.

    It gives you access to the view that has been in focus before. Or is the currently focus view and it also gives you access to the view that focus is going to move towards.

    The other important object that you get access to is UI focus animation coordinator. And this object is what you need if you want to add your own custom animations and have them run with the exact same timings as the focus transition animation. And that way, even if we tweaked the animation timings in the future, your animations will still be in sink. Now again, just a quick mention that table and collection views also provide additional delegate methods for doing the same thing. OK so that is the theory. So let's take a look at how you can actually create this label in fact in your own app. So let's take a look at some quote for this. Here we are in our own custom UI collection view cells subclass that we created for this effect. And all this cells are set up in a way that they have this image view that gets the parallax effect applied automatically because we switched this property on. But we also already have a UI label in all of those cells.

    This is already there, but we just-- by default, set the alpha to zero so that it's hidden by default.

    And now we overwrite that didUpdateFocusInContext method for this UI collection view cells subclass. And this means that every time a particular cell takes part in a UI focus transition, this method will be called. And then we can use the UI focus animation coordinator to add a coordinated animation and then we check if the current cell which itself in this case is currently focused and depending on if it's focus or not, we just adjust the alpha, we just basically just an implicit animation that instructs the focus engine to render this animation together with the focus transition animation. And that is pretty much it. This is how you can add your own custom animations with the exact same timing as the focus update transitions. So this is how you can respond to focus changes. Now let's move on to something that we call focus guides.

    Sometimes in your apps, you might run into a situation where the focus engine just doesn't move focus because it just can't find a focus overview in the rectangular area, it's searching for it. But still, sometimes in those cases, you might have a pretty good idea of where focus should go in that case. Let's take a look at this example here. Now the top left button is in focus and if we swipe to the right, it does exactly what we would expect. So it looks at its rectangle here, it finds the top right button and then it just moves focus over there. But what happens if we move down now, if we swipe down now? Now if we just swipe down, the top right button isn't focused, the focus engine looks at this area and there's nothing there, so of course nothing happens. But in the UIs like this, people would probably expect the focus to move to the bottom left button instead. And we can achieve this by helping the focus engine out with something that we call a focus guide.

    A focus guide is something that is part of the view hierarchy but it's not visible and then no way displayed to the user. But the focus engine can see it as a focusable element.

    So we can just add a UI focus guide here and when the focus engine searches for focus overviews, it will find the focus guide but then the focus guide itself is not visible in the UI. So it cannot really become focused. But what focus guides have is they also have a preferred focus view property. And so we can just configure this focus guide to point to the bottom left button as its preferred focus view and that instructs the focus engine, when it finds this focus guide to move focus over to the bottom left button instead.

    And so focus just jumps over there. So that solves the problem, but naturally we would also expect this to work back.

    So if I swipe to the right now, focus should move back up to the top right button. But the way this is set up right now is the focus guide still points the bottom left button so nothing would happen. So what we need to do here to enable correct behavior is that we just need to reconfigure the focus guides preferred focus view based on where focus is right now. And then if we do that and if we now that the focus is on the bottom left button, if we reconfigure the focus guide to point to the top right button instead, it all works and the focus engine will move focus over to the top right button again.

    So this is how it looks like when it works. Let's take a look at the code for this. And there are two things that we need to do here.

    The first one is we need to create the focus guide. So we're-- here we are in the view controller that is managing this button example and so we just used the ViewDidLoad method to add the focus guide programatically. Next thing we need to do is, we need to instantiate a UI focus guide and UI focus guides are lay out guides. And if you're familiar with auto layout, you know that you can add layout guides to the view. And so we just add this focus guide this root view controller's view.

    And then we use auto layout to position this focus guide and then we also use it to give it within height based roughly on the buttons that are already there.

    So this is how we create the focus guide. But then we need to set the preferred focus view and we do that by overwriting the didUpdate focus on context method for this view controller. And this one gets called every time focus changes in this view controller.

    Then we have to check what is going to be the next view in focus and we can do this by getting the UI focus update context and ask it before the next focus view. And then based on what is going to be the next focus view, we want to reconfigure the preferred focus view on the focus guide and we are interested in two specific cases here. The first one is, if focus is moving to the top right button, we want to configure the focus guide to point to the bottom left button. If focus is moving to the bottom left button instead, we want to have the focus guide point to the top right button. In all other cases, we don't really care and so we just disable the focus guide by setting the preferred focus view to no. And that's all we need to do to make this button example work. So this is using focus guides.

    The next best practice is something that I like to show you, a feature that we added to x code to help you debug any focus issues.

    Before that, I like to switch to a demo. So here we are in the UIKit catalogue app for tvOS which is a sample app that you can download from developertotheapple.com. And this is just a very simple app that gives you an overview of all the controls that are available on tvOS and more importantly how to use them. And now, I want to just go back to this focus guide example that we were just talking about to show you something here.

    So I have these focus guides as an example here. And here we have those buttons that I was talking about. And now you can see that I can switch focus between the top left and the top right button. But what you can't see here is, although I'm trying to get to the bottom left button, for some reason that doesn't work.

    I can also show you the TV remote here so that you see if I swipe left and right that works, if I swipe down here, and even if I do it from the top left bottom, nothing happens.

    So something is clearly wrong with the bottom left button. Now, to diagnose what the problem is, we've added a new diagnostic API.

    And so, to use that I want to break in this code that is managing this view-- the view controller that is managing this example.

    For that, I'd like to just activate break points that I've set earlier here. Go back to the simulator.

    And now if I switch between those buttons, I will hit a breakpoint. I'm basically just doing this-- I'm basically just doing this to get access to the button that is conveniently defined as a property here in this view control. So we are in the focus guide's view controller, which is the view control that controls this button, example, and we have the bottom left button provided as an outlet and as a property here.

    So that allows me to just go into the debugger and use LDB to, like, poke at this object and see what's wrong with it and I could do something like this PO bottom, left button. But we can do better than that because I already mentioned that we provide a new diagnostics API which is called-- it is called like this whyIsThisViewNotFocusable. So we can basically just ask this button or other UIView and the view hierarchy, why it is not focusable? Now if you've seen this in the documentation already and if you've tried that in your own projects and you probably know that if I would just hit "Enter now," it wouldn't work because we're in the swift project. And this a diagnostic API which is not part of the public interface. And this means that we have to do this a little bit differently in swift.

    But it's very easy because we can just use the object and see one time to help us with that. And the way to do this is to just-- it's called performSelector. And then just pass this name of this API. And that will call this API on the button.

    Now if we look at this-- what this API does, it runs a few checks on this view and tries to figure out why something cannot become focusable.

    And in this case, if found an issue that this view has user interaction enables it to NO. And of course, it's not enough for views to have-- to just return through to can become focus. There are some other conditions that needs to be met, in this case, for some reason, user interaction enabled is set to NO, so that is a pretty easy fix of course. I just stop the app, just go into the story board that manages this button, so here we have the bottom left button. And if I look at the properties here, I can see user interaction enabled is not set and I just set this here and run the app again. And now we'll go back over to the focus guide example and now I can move to the bottom left button like you would expect. And also, it works for the focus guide. So this is one thing that I wanted to show you but there is another thing I want to show you. And for that I go into a separate part of this same app. And this is about something that we provide to help you debug how focus moves, how to focus engine makes those decisions of where to move focus next.

    So let's just say we are here in this collection view. And now I'm enabling breakpoints again because I've set another breakpoint here.

    And now if I press down now, so if I'm trying to go to the element below I will again hit a breakpoint. And here we are again breaking in didUpdateFocusInContext.

    Now, this time I'm breaking in this method because I want to get access to the UI focus update context update and which we can also find here in the variables view.

    And now, of course we could use ldb again and we could, like, PO something and figure out what the view is that focus is coming from as well as which view focus is going to.

    That, of course, would also work but we can do better than that. We also have this quick view button here which you can just press.

    Or you can just press the space bar when the context is selected. And this brings up this custom image, so we've implemented a custom quick look that helps you debug focus. Now, you can see there is the UI that we currently see in the background. But we also have a couple of overlays that tell us everything about how focus moves here.

    There's this red square which, in this case, is the cell that is currently-- that has-- it's currently focused.

    And if you look closely, you can also see that there is this rectangle, with the dotted line, a little bit lighter red, which is the area that the focus engine is searching for other focusable elements. And in there, it finds two other cells which are marked by these purple regions here. And so, there are two other focusable elements in the area that the focus engine is searching for.

    And this also shows you that the focus engine looks a little bit further than just what's on screen right now. It also tries to find things that might be off-screen right now, which is pretty helpful if you have a collection view and there are more cells off-screen right now that you want to reach. And the last thing that you can see is that it also provides this red blotter around this particular cell. And this means that this is going to be the cell that focus in moving to.

    The other great thing about this-- this is just an image which we provide and so, you can open this with preview and then you save this image to disk, you attach it to an email and then communicate with other engineers on your project to discuss those focus issues that you might be seeing here.

    So what you've seen here is a new diagnostic API that we added to UIView called, whyIsThisViewNotFocusable that you can use to figure out why something cannot become focused and I've also shown you how to use that in the swift project, in which implemented this custom quick look for UI focus update context which gives you this image that you can use to debug focus issues. So these are the tools for debugging focus.

    And the last thing I want to talk about today is how you can handle button presses. As you know, the serial mode has a play/pause and a menu button and you might want to take advantage of those in your apps. Now basically, if you structure your UI with the standard components and you have like a navigation view controller hierarchy then many of those buttons will already do the right thing and you don't have to do anything extra.

    But sometimes, you might want to have some custom behavior and you do want to listen to those button presses specifically.

    And here is how you can do that. There's two ways to do that, the first one, and probably the easiest way to do this with UIKit is using a gesture recognizer. Now we've added a new API to UI gesture recognizer that allows you to specify allowed press types.

    And this is just an array with a couple of constants for the buttons that you want to listen for. These constants are defined in an enum UIPressType.

    Now let's take a closer look at that to see which buttons you have access to. So of course we have a constant that is called "Select" which is for the touch area, if you just click on the touch surface of the remote. And then we also provide constants for the menu button as well as the play/pause button. And these are all physical clicks on the new remote. But we do have a couple more constants that you can use here.

    And this is something that is very useful if you use this feature where you can just tap on the edges of the touch surface which will also result in button presses reported through this API. And these are the up, left, right and down arrow constants. This is also pretty useful if somebody is using a classic remote because this classic remote has physical button presses for those directions as well as if somebody is using a game controller. But if you're using game controller to like, if you want to work on a game and you want to, probably, have a look at all our game controller APIs instead. But you can also control your standard UIKit user interface, using an attached game controller.

    But, we will have another session about game controllers that will tell you a lot more about other APIs, specifically for games.

    Now, use these constants to detect all kinds of button presses in those situations where you want to have some custom behavior, beyond what the focus engine provides automatically. There's two more things that I want to mention here if you use gesture recognizers, the first thing is, if you want to have different things happening with different buttons which is probably what you want to do, you need to use separate recognizers.

    So just set up separate recognizers only listening for those button or buttons that you want to have a specific action for.

    And the other thing here, of course, you can still use gesture recognizers for detecting all the regular touch gestures on the touch surface on the remote. So tap, swipe, pan and long press gesture that are all also supported with the touch remote.

    This is using gesture recognizers but we also provide lower level event handling. And this works exactly like it does on iOS.

    So along the responder chain, you can override any call backs to respond to specific button presses on the remote. And for that we added new API to UIResponder which is called pressesBegan, Ended, and Cancelled So this very, very similar to what you might already know from iOS with touchHasBegan, Changed, Ended, and Cancelled.

    And it works the same way, just in this case, it gives you access to physical button presses on the new remote.

    Now talking about how similar it is to the touches events, of course, the touches events are also available, because there is a touch surface on the remote and you will get access to those events through this API as well. One thing to note here though is that as part of those events you will, of course, be able to access coordinates for where those button presses happen. Now, here on this platform, hopefully, you will not touch this screen directly. And so, we don't really know specific coordinate locations on the screen.

    And the way we deal with this on this platform is that we just use the center of the currently focus view to provide you with touch coordinates and then we just calculate everything else from there. So this is how you can handle button presses and your UIKit apps.

    And this also concludes the five best practices that I wanted to share with you today. So, please find me or my co-workers in the Q&A lounge later if you have questions about those five or if you are looking for other things that I didn't cover here. So in summary, we really created the focus engine to make it quick and easy for you to create rich user interfaces for tvOS that feel really great with the new Siri remote.

    And, please take advantage of the focus model and that the focus engine handle most of the interactions for you.

    Because that way, you will ensure that the experience is great across all apps. And also, you can get a lockdown with just using the standard controls which we optimized to work with the focus model. And just using the standard controls that will probably be the fastest way to come up with a great user interface quickly. Now and with all our frameworks and APIs, you will get the fastest results if you work with the focus engine and not against it, which is why I think it's very important and crucial to understand how the focus engine works. We have some more information about the topics that we've just discussed in this first section on our tvOS landing page at developertotheapple.com, so please have a look at the tvOS human interface guidelines which will discuss a lot of the things you heard about earlier, about designing for this platform. And then we have the app programming guide for tvOS that will go into great depth on how the focus engine works.

    And then, also, please check out the UI focus environment reference documentation as well as the header flats for that.

    Now, all the examples that I had in this segment are taken from the UI catalogue for tvOS sample app which is also available on developertotheapple.com.

    Thank you.

  • Looking for something specific? Enter a topic above and jump straight to the good stuff.

    An error occurred when submitting your query. Please check your Internet connection and try again.

Developer
  1. Videos
  2. Apple TV Tech Talks
  3. Focus-Driven Interfaces with UIKit

Discover

  • macOS
  • iOS
  • watchOS
  • tvOS
  • Developer Program
  • Enterprise
  • Education

Design

  • Accessibility
  • Accessories
  • Adaptivity
  • Apple Design Awards
  • Fonts
  • Design Videos
  • Marketing Guidelines

Develop

  • Xcode
  • Swift
  • Downloads
  • API Reference
  • Guides
  • Sample Code
  • Videos

Distribute

  • App Store
  • App Review
  • iTunes Connect
  • TestFlight
  • Enterprise
  • Safari Extensions

Support

  • Developer Forums
  • Contact Us
  • Bug Reporting
  • License Agreements
  • System Status
To receive the latest developer news, visit and subscribe to our News and Updates.
Copyright © 2017 Apple Inc. All rights reserved.
Terms of Use Privacy Policy Report Bugs Feedback
简体中文 日本語 한국어