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.
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
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
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
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
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
Now that there is sometimes there are cases
where it's a little bit ambiguous what should happen
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
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
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
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
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
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.
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.