WWDC2016 Session 215

Transcript

[ Music ]
[ Applause ]
>> Good afternoon.
Hi. My name is Matthew
Ricketson.
I'm a software engineer working
on UIKit, and today we're going
to talk about Focus
Interaction on tvOS.
Last year we introduced
tvOS, a great new platform
for building apps on Apple TV.
And whether you're building
a brand new app for Apple TV
or looking to port an existing
app over from another platform,
it's immediately obvious
that Apple TV is unlike
other Apple devices.
There's no touchscreen on a TV
or a mouse because these forms
There's no touchscreen on a TV
or a mouse because these forms
of user input just
don't make sense
in a living room environment.
Instead, we use this, a
remote, like the Siri Remote,
in order to control
Apple TV from a distance.
The Siri Remote and Apple TV
have been designed together
to provide the best
navigation experience.
But Apple TV also supports
many other input devices,
like game controllers,
Bluetooth keyboards,
and the new remote app.
And sometimes users might feel
more comfortable using one
of these other input devices in
order to control their Apple TV,
and tvOS helps you
support all of these
through a user interaction
model that we call Focus.
With Focus interaction, users
indirectly control the UI
through a single focused
user interface element
and they can move focus
around the screen
using any input device.
Users will expect that your
apps are optimized toward great
with Focus interaction.
And to help with that, UIKit
provides built-in focus behavior
for all of its standard
controls; however,
you may also want to customize
the focus behavior in your apps
in order to take them
to the next level
and provide an even
better user experience.
And for that, UIKit
exposes a Focus API.
Now today's talk is
about that Focus API
and we split it into two parts.
First, we're going to
dive into what's new
in the Focus API
this year in tvOS 10.
And then in the second part
of the talk, we're going to go
into an extended case study
on how to build a custom,
fully focusable control
completely from scratch.
This is a great demo
that will show you how
to get started building
unique interaction experiences
in your tvOS apps.
Now a quick note
before we get started.
We're going to assume that you
have at least some familiarity
with the Focus API
and the basic concepts
with the Focus API
and the basic concepts
of how Focus works on tvOS.
But even if you're new to
the platform, don't worry.
You can still generally
follow along, and at the end
of the talk today, we'll call
out some useful resources
to help you get started with
building apps for Apple TV.
So what's new in tvOS 10 and to
start, we've added some new APIs
to enhance the preferred
focus system.
Now as a quick review, when
we talk about preferred focus,
we mean the process
of determining
where Focus should show
up after a Focus update.
Whenever Focus updates,
for example when your app first
launches, the Focus engine needs
to know where focus
should be directed to.
It does this by asking your app
where it prefers
Focus gets directed.
Let's look at a specific
example.
When your app first launches,
the Focus engine is going to try
to figure out where Focus
should show up by default,
to figure out where Focus
should show up by default,
and it's going to start by
looking at the focus environment
that we're updating Focus to.
And when our app first
launches, that's the window.
In this case, the Focus engine
will ask the window what's its
preferred Focus view is.
The window delegates
this responsibility
to its root view controller,
which could also return some
other view in the hierarchy
as its preferred Focus view.
The Focus engine will then ask
that view what its
preferred Focus view is
and it will continue
following down this chain
until it reaches the end, which
is the last focusable view
that it found as the new
Focus view on screen.
Leveraging the Preferred
Focus System is important
to provide a good
user experience
in complex apps, especially.
So that focus is directed to
the correct parts of the screen
at the appropriate times.
In tvOS 10, we're
providing a new property
that allows your apps to
easily express complex Focus
preferences and the name of this
property is appropriately called
preferences and the name of this
property is appropriately called
Preferred Focus Environments
declared
in the UIFocusEnvironment
protocol and it returns an array
of objects that also conform to
the UIFocusEnvironment protocol.
And this property has
two primary benefits.
First, by returning objects that
conform to UIFocusEnvironment,
you can specify that focus be
directed to any environment
on screen, not just views but
also view controllers directly.
The second benefit
of this property is
that it returns an array of
these focus environments,
which allows you to specify
an ordered list of preferences
and this enables complex,
multipart-preferences
to be expressed much
more concisely.
And there's a specific pattern
where we can see this happening
that Preferred Focus
is commonly used
in which is custom
container view controllers.
Let's look at an
example of that.
Say we have an app with a
structure that looks like this.
We have a container
view controller
We have a container
view controller
with two child view controllers.
In this example, we want
our container to prefer
that focus show up in the left
child view controller first,
but if that's not possible,
focus should be directed
to its right child
view controller.
And we can express this logic
very concisely using the new
preferredFocusEnvironments
property.
Here, we override
preferredFocusEnvironments
to return an array of both
children with the left child
as the first item in the array.
This is great because
we don't have
to check ourselves whether
the left child view controller
actually contains
anything focusable.
We don't have to know anything
about the contents
of that controller.
We just tell the Focus engine
what our preferences are
and it takes care of
the hard work for us.
So if our left child
view controller
in this example happened to
not contain anything focusable,
the Focus engine will
automatically fall back
to that right child
view controller instead.
And in this example, maybe it
does find something focusable.
So the
preferredFocusEnvironments
property helps us to express
these preferences much more
clearly and concisely,
and if the first item doesn't
produce anything focusable,
we can easily fall back to the
other environments in the list.
Next up, we have
another enhancement
to the Preferred Focus
System and this is
for more specific use case
involving restoring Focus
after view controller
transitions.
So before we introduce the API,
let's first look at an example
to illustrate what exactly
we mean by focus restoration.
Say we have an app
that looks like this.
It's a simple view controller
with a menu of buttons.
And our root view
controller has preferred
that by default we want our
first button to become focused.
It did this using the
preferredFocusEnvironments
property that we just looked at.
Now suppose the user moves to
the last button in the list
and selects that button
to present a detail
view controller.
In that case we're
interested in is
In that case we're
interested in is
when this detail view
controller gets dismissed.
After the dismissal, focus
needs to be restored back
to our root view controller.
Now the user would
probably expect
that focus gets restored
back to the button
that was last focused,
before our presentation,
which is the last
button in our list.
However, if we ask our
root view controller
at this time what its preferred
focus environments are,
it would still direct us to
that first default button.
And so instead, the Focus engine
automatically remembers the last
focus item for us so that after
the transition is complete,
it automatically restores
focus to that last button
that the user would expect.
This is behavior that
existed in tvOS 9.
While this is almost always
the behavior that both the user
and often the developer
expects, there are some cases
where you might want to
restore focus to some other part
of your user interface.
Suppose for example that while
our detail view is presented,
our app's underlying
data model changed
so that the last button
now represents a completely
different action or data
item that it did previously.
In that case the user might not
expect focus be automatically
restored back to that last item.
In that case, we
want the Focus engine
to use your view controller's
preferred focus environments
in order to determine where
focus should be restored to.
And in tvOS 10, we're
providing an API
that allows you to do just that.
It's called
restoresFocusAfterTransition.
It's a Boolean property
defined on UIViewController
and the way it works
is very simple.
If set to true, the view
controller will use the
default behavior.
It'll tell the Focus engine
to use its default behavior
restoring focus to the last item
that was focused before
the transition occurred.
If set to false, however,
then the Focus engine will
instead consult your view
then the Focus engine will
instead consult your view
controller's
preferredFocusEnvironments
giving your app a
chance to control
where focus gets
directed to on screen.
The property is set to
true by default to maintain
that previous default behavior
and it affects view
controller presentation,
like we just talked about,
but other common built-in view
controller transitions as well
such as navigation pops and
moving focus back and forth
between your view
controller and the tab bar.
We recommend that when
using this property,
set it always be true or always
be false so that focus updates
within your view controllers
in a consistent and
predictable way.
We really hope that this
property will help you solve
some of those tricky edge cases
that you found in your app.
To show you how to use
both of these properties
that we just talked
about, I'd like to invite
up my colleague Brandon
for a quick demo.
[ Applause ]
>> Hi, everyone.
My name is Brandon and I'm
here today to show you how
to take advantage of some
of the new Focus APIs
available in tvOS 10.
So I've been working on
a simple calendar app
and it's coming along
pretty well so far.
You can view your events for a
given week and you can switch
between weeks using the
next and previous buttons.
Now when the app
launches, we initially focus
on the previous button
when I think it would
actually be a better experience
if we focused on the
user's next event.
So let's go modify
our app to do that.
So to direct focus, we need
to override the
preferredFocusEnvironments
property.
This returns an array
of UIFocusEnvironment
for the focus engine
to search to search.
We'll start by adding our
upcoming events for the rest
of the week to our array.
If we have no more upcoming
events, then we want focus
to default to the next button.
So we'll add that to
our array as well.
So we'll add that to
our array as well.
Now let's run this,
see if it works.
All right, so this time when
the app launched, we're focused
on the super secret party I'm
hosting after this session.
Now, I wonder what would happen
if I canceled this party.
When an event is canceled,
it becomes grayed
out and unfocusable.
So I would expect focus would
just go to our next event,
which is a tvOS lab
tomorrow morning.
But a good developer
always tests their code.
So let's go try this out.
So I'm going to go
to my AppDelegate
and cancel my not-so-secret
party and rerun this app.
All right, just as we
expected, when the app launched,
we're focused on the tvOS lab.
So because our first
preferred focus environment was
unfocusable, the Focus
engine just moved
to our next preferred
focus environment.
We didn't have to modify
any of our code to do that.
The Focus engine
handled it for us.
Now if you want to view
the details for an event,
you can select it to
bring up the Details page.
From here, you can swipe
left to right to go
to the next or previous event.
I received some bug
reports from beta testers
that when they exit this view,
the focus isn't on the event
that was just selected.
So in this case, we've
selected the bash.
So if I menu out, I would expect
that we would be
focused on the bash.
Instead, we're still
focused on the tvOS lab,
which is our first available
preferred focus environment.
So all we need to do is update
our preferredFocusEnvironments
code to return our
selected event
as our preferred
focus environment.
So let's go back to our
CalendarViewController,
and I have the selectedEventView
property here which keeps track
of the selected event when
we're in the Details page.
So if this property
exists, I'll return it
as my first preferred
focus environment.
All right, let's run
this, see if it works.
Okay. So I'll select the
tvOS lab, move the selection
to the bash, and then menu out,
and we're still focused
on the tvOS lab.
And I'm remembering now
that Matt mentioned earlier
in the session that by default,
the Focus engine
does not consult your
preferredFocusEnvironments
when restoring
from a view controller.
So to change that behavior,
we need to set the
restoresFocusAfterTransition
property to false.
So let's go do that in our
[inaudible] coder method
and rerun the app,
see if it works now.
All right, we'll select
our tvOS lab event again,
move our selection to
the bash, and menu out.
Awesome, so now we're
focused on the bash,
which is exactly what we wanted.
So by using the
preferredFocusEnvironments
and restoresFocusAfterTransition
properties,
we're able to provide a much
better experience to our users.
we're able to provide a much
better experience to our users.
Now I'd like to invite
Matt back up on stage.
[ Applause ]
>> Thanks, Brandon.
That was a really great demo.
Using these two new properties,
we hope that you can reduce the
complexity of code in your apps
and also provide a
better user experience.
Now, next up I'm really
excited to announce
that we're bringing focus
interaction support directly
into SpriteKit.
Prior to tvOS 10,
SpriteKit developers had
to manually implement
focus interaction
in their SpriteKit games
by manually keeping track
of their own state and
handling user events directly.
But now in tvOS 10, we're
extending the Focus API,
the same API you're
used to in UIKit,
to also support your
SpriteKit games.
But first, what would
this be useful for?
But first, what would
this be useful for?
Well the first and most obvious
use case for focus interaction
in games is game menus.
Your users will expect
that menus in games feel
and behave similar to
menus in other system apps.
The Focus Interaction model also
makes sense for board games,
where users navigate around
a two-dimensional game board
and select items on that game
board, maybe move those around.
And in fact, Focus Interaction
makes sense for any type of game
where selection is a
core gameplay mechanic.
And in any of this use cases,
again users will expect
navigation and selection
to feel similar to the
system focus behavior.
Otherwise, your app might feel
weird or broken, unintuitive.
And so to help with that, we've
extended the same Focus API
that you're used to in UIKit to
now also work with SpriteKit.
that you're used to in UIKit to
now also work with SpriteKit.
This is a shared API,
and what this means is
that SKNodes are now able to
opt in to becoming focusable
and taking advantage of all
of the Focus engine's
built-in capabilities.
UIKit and SpriteKit have been
integrated to allow focus
to move freely between
your views and your nodes
so you don't have to handle
those use cases yourself.
So how exactly does this work?
First, let's review how
Focus works for UIViews.
Prior to tvOS 10, UIViews were
the only user interface elements
that were capable
of becoming focused,
and they defined their
focus ability using the
canBecomeFocused property.
UIViews also conform to the
UIFocusEnvironment protocol.
And this allows views to get
focus update notifications
and also control the
behavior of focus
within their subview hierarchy.
So to support SpriteKit
focus, we're going to want
to bring these same
capabilities to SKNodes
and we've made some
changes to support that.
We're abstracting
these same capabilities
out into their own protocol
that we call UIFocusItem.
This protocol defines both
that canBecomeFocused property
and conformance to the
UIFocusEnvironment protocol.
Next, we refactored
UIView and extended SKNode
to conform to this new protocol.
And this allows both
UIView and SKNode
to share these exact same API
while not requiring any changes
in your existing UIKit code.
We've also made additions to
other parts of the Focus API
in order to take advantage of
this new UIFocusItem protocol.
First, let's look at the
UIFocusUpdateContext class,
which provides contextual
information during focus
update notifications.
In order to support focus
updates to SpriteKit nodes,
we're introducing two new
UIFocusItem based properties:
previouslyFocusedItem
and nextFocusedItem,
and these tell you which items
are involved in the update.
We've made a similar
change to UIScreen,
introducing a new focusedItem
property that returns an object
to type UIFocusItem and
this allows your app
to query what the current focus
item is at any given time.
Now there's one more API
change worth mentioning
but it requires a little
bit more background.
In tvOS 9, the UIFocusItem
protocol defined the
preferredFocusView property.
And prior to tvOS 10, this was
how apps defined their focus
preferences, like we were
talking about earlier.
But you can probably
see a problem with this,
which is that it
returns a type of UIView.
And if we're going to support
SpriteKit, we're going to need
to define focus preferences
to our SKNodes.
to define focus preferences
to our SKNodes.
And so this isn't going to work.
But luckily, earlier
in the talk,
we introduced this new
preferredFocusEnvironments
property, which does
the same thing.
But because it returns an array
of UIFocusEnvironment objects
and now SKNode conforms to the
UIFocusEnvironment protocol,
we can now define focus
preferences to views,
view controller, SKNodes,
any object that conforms
to UIFocusEnvironment.
And this makes defining
focus preferences
in your environments
much easier and concise.
And because
preferredFocusEnvironments takes
care of all the use cases
for preferredFocusView does
but also provides
these other benefits
that we've talked about,
in tvOS 10 we're going
to deprecate preferredFocusView.
So if you're currently
using preferredFocusView
in your applications,
we recommend upgrading
to preferredFocusEnvironments
instead.
We think this will really help.
So that's Focus Interaction
support in SpriteKit.
So that's Focus Interaction
support in SpriteKit.
Focus API now supports generic
focus items using this new
UIFocusItem protocol.
Both UIView and SKNode
conform to this protocol.
And for SpriteKit
developers, you can now opt
in to supporting focus
to take advantage
of all the Focus
engine's capabilities.
For UIKit developers that don't
use SpriteKit in their apps,
there are no changes required.
The view-based API
with the one exception
of preferredFocusView is still
available for your convenience.
We do encourage you, however,
to start using this new API
in your code to take advantage
of more generic and
future features.
For more details on exactly
what you need to do in order opt
in to focus support in
your SpriteKit games,
we recommend watching
the What's New
in SpriteKit session happening
this week, where they go
into more detail on exactly
what you need to do to opt in.
So that's Focus Interaction
support for SpriteKit.
So that's Focus Interaction
support for SpriteKit.
And that concludes our overview
of what's new in tvOS 10.
And so for the next part of our
talk, we're going to go in-depth
with a case study on how
to build a fully custom,
focusable control.
And for our example today,
we're going to use a
five-star rating control.
Now we've already done some work
and we've built a first draft
of this control and I'd
like to show that to you.
We just used the normal UIButton
class and presented the rating
as the title of the button.
If you select the button,
it'll bump up the rating,
and if you keep selecting
the button,
it'll cycle through all
the available ratings.
Now this is okay.
It gives us the functionality
that we need, but we really want
to take our app to
the next level.
And this control, it's
good but it's not very fun.
It's not very interactive.
And so we thought long and
hard about this and we came
up with a new design and
this is what that looks like.
That's a lot better.
Instead of just saying
one-star or two-star,
we now visually indicate our
rating using actual stars.
When you select the control,
you go into an editing mode,
where you can use
the Focus system
to change our rating
between the stars.
And when we're done, we
just press Select again
and we exit editing mode.
This is a great example of
a control that is optimized
for focus interaction and
we're going to walk you
through building this
control completely
from scratch using
the Focus API.
And for that, I'm going to hand
things back over to Brandon.
[ Applause ]
All right, thanks, Matt.
So I have a project here
which contains our simple button
control, but it doesn't look
as nice as the one
Matt just showed us.
So let's just delete that.
Let's go ahead and
drag in a view
to represent our new control.
We'll set up some constraints
on it quickly, so 100 points
We'll set up some constraints
on it quickly, so 100 points
from the top, a width
of 650, a height of 150,
and we'll center it
horizontally in our container.
Great. Now I've already
created a rating control class
to represent this
control, so let's assign
that as a views class.
And let's go check out
this rating control class.
We chose a subclass
from UIControl
because it provides a lot of
functionality to us for free.
For example, it determines if
the control can become focused
or not based on its
enabled state; however,
it doesn't have a
focus/unfocused appearance.
We have to provide
that ourselves.
So let's go do that.
We'll start by adding a corner
radius and a background color
and then we'll override
didUpdateFocus in context
with coordinator to
provide both a focus
and unfocused appearance.
So if the next focus
item is our control,
then we'll configure the focus
appearance, which just consists
then we'll configure the focus
appearance, which just consists
of scaling the view,
adding a shadow,
and changing the
background color.
If the previously focused
item is our control,
then we'll configure the
unfocused view or appearance,
which just rests all
of our properties.
Now before I run this,
I also want to add motion
effects to our control.
Motion effects makes your
app feel more responsive
and helps the user find
the focus item on screen.
So to do that, I'll
create a motionEffectGroup
to add horizontal and vertical
motion when I move my finger
around the touch surface.
Now I need to go back, and when
our control becomes focused,
I will add the motion effect,
and when it becomes unfocused,
I will remove the motion effect.
Now I make all these changes
within addCoordinatedAnimations
block.
This way, our property
changes are in sync
with our focus animations.
So let's see how this looks.
All right, so what we've done
so far is create a very basic
control which has both a focus
and unfocused appearance
and has motion effects.
So it moves when I move my
finger on the touch surface.
But this is supposed to be
a five-star rating control
and we don't have any stars yet.
So let's go add those.
So first we need to
add some properties
to store our control state.
And then in our awakeFromNib
function,
we'll add a horizontal stackView
and add five stars to that.
I've already created the star
classes to save some time,
but if you're following along,
I configured their focus
appearance using the same
process that we just saw.
Now when the user selects the
control, I want them to be able
to edit the current rating.
So I'll add a
selectGestureRecognizer
to our control.
And when that's triggered,
I'll toggle the editing state
and request a focus update.
When a focus update happens,
it consults our
preferredFocusEnvironments.
So we'll override that property.
And if we're editing,
we'll return our starViews
as our
preferredFocusEnvironments.
Otherwise, we'll just return
our super implementation.
Let's run this, see
how it looks.
Okay, so this time
when our app launched,
we have some stars
in our control.
And when I select the control,
focus moves to the first star
within the control; however,
I'm not actually able
to move focus to
the other stars.
This is because there's some
space between the stars.
So when we try to move focus
to the right, we actually end
up focusing on our control,
which just directs focus back
to our first star using
preferredFocusEnvironments.
So to fix this, we want to
make sure our control is not
focusable when we're editing.
So let's override
canBecomeFocused
and we'll return false if our
control is currently editing.
and we'll return false if our
control is currently editing.
So let's run this, see
if that fixes things.
All right, that's much better.
So now I'll able to move
focus between the stars.
But it's difficult to tell
what the current rating is
because we don't provide
any visual feedback.
So to do that, we need to
update the current rating
when our focus changes.
So let's go back to our
didUpdateFocus function,
and at the bottom,
if we're editing,
we'll set the current
rating based on the index
of the currently
focused starView.
And let's go back up to
our current rating property
and we'll tie that directly
to the isSelected
property on the starViews.
And this property just sets the
background color on the stars.
So let's see how that looks.
Okay, so now when I select
the control, it's easy to tell
that the first star is selected.
And when I move focus, all the
star select remain selected.
So it's easy to tell what
the current rating is.
So this is pretty good
but it's not great yet.
Right now I'm able to move
focus outside the control,
and I don't want
to be able to do
that when I'm editing
the current rating.
Also, when I select the control,
we always reset the current
rating back to one star.
I think it would be better
if we kept the current rating
and just focused on
the last selected star.
So let's go make those changes.
So we'll start by overriding
the shouldUpdateFocus
to restrict focus movement.
So if we're editing and the
next focus item is not one
of our star views,
then we'll return false
to say no, focus can't move.
Also, in our
preferredFocusEnvironments code,
we want to return our last
selected star if we're editing
we want to return our last
selected star if we're editing
and the current rating
is greater than zero.
So this way we don't reset
the current rating every time.
Let's run this one more
time, see how it looks.
Okay, now I'm no longer able
to move focus outside
of the control.
And when I select a control, the
current rating stays the same
and we just focus on
the last selected star.
So that completes
our custom control.
By utilizing the Focus
APIs, we were able
to create a pretty complex
yet very useful control.
Now I'd like to invite
Matt back up on stage.
[ Applause ]
>> Thanks, Brandon.
I rate that demo
with five stars.
Okay, we chose that demo
because it was a great example
of using many different parts
of the Focus API in order
of using many different parts
of the Focus API in order
to create a rich focus
interaction experience.
And there are just a couple
parts of the implementation
that Brandon showed us that
I want to highlight again
because they're important
for really creating a
great user experience.
The first tip we have is
to subclass UIControl.
UIControl provides a lot of
basic functionality for free,
for instance, as Brandon said,
defining the focusability
of your controls based on
its IsEnabled property.
So when you're building
custom controls,
you should also subclass
from UIControl.
We also used the focus
animation coordinator in order
to define our focus-related
animation changes
when changing our focus state.
This is also really
important for making sure
that our focus animations
stay in sync
with other focus animations
happening in other parts
of the user interface.
And we do this to make sure
that focus naturally flows
around the screen when
the user is moving
around the screen when
the user is moving
between different controls.
So when you're defining
animations
for your focus appearance,
please use the focus
animation coordinator.
And the last tip is
to use motion effects.
Brandon showed us how
to use motion effects
to create a little
bit of movement
when you place your thumb on the
Siri Remote and do a little bit
of movement but not enough
to actually move focus.
You can use the UIMotionEffect's
API
to implement this
behavior very easily.
This is important because
it allows your users
to get this direct
connection to your app
so that they get
immediate feedback as soon
as they start using
the Siri Remote.
It also helps the user
locate focus on the screen
so that they can sit down
in front of their TV,
wiggle the remote around,
and immediately the
focus element pops out.
Before we wrap us, just
a few notes on testing.
The first is to point out that
not all input devices have the
The first is to point out that
not all input devices have the
same capabilities.
And this is definitely
important when it comes
to testing your custom controls.
Now the good news is that
if you use the Focus API
to build your custom controls,
like we did in this demo,
then your control should work
with any of the input devices
that we talked about
earlier: Game controllers,
Bluetooth keyboards, the Siri
Remote, all of those other ones.
But not all these input devices
have the same capabilities
so that if your custom
control relies
on some custom event handling
or gesture recognition,
for example, let's say
for example you're
using the Siri Remote
which generates touch events
from its touch surface
and you're using that
to drive some capability
within your custom control,
well if a user is using
a Bluetooth keyboard,
they can't generate
those touch events.
And so you'll have to do
some extra work to make sure
that your control can behave
correctly and be functional
for all users, in
all situations.
for all users, in
all situations.
And so definitely
test custom controls
that use custom event handling
with different input devices.
Try out a Bluetooth keyboard,
pick up a game controller,
very important to maintaining
a good user experience.
And finally, please,
please test your controls
with accessibility.
The good news here is that the
Focus engine again does some
work for you.
For example, if the user wants
a high-contrast user interface,
the Focus engine will
helpfully put an extra ring
around the currently focused
item to really make it pop
out on the screen and
make it easier to see.
But for other accessibility
features, such as VoiceOver,
you're going to have the do
the same kinds of custom work
that you're used to
on iOS to make sure
that your controls
behave well on tvOS.
And so please test your controls
with features like VoiceOver
to make sure that they behavior
really well in all situations.
So that's our talk today.
We introduced two
new API properties,
preferredFocusEnvironments and
restoresFocusAfterTransition
to help manage preferred
focus in your app.
We also announced the new
focus interaction support
for SpriteKit and we think this
will really help reduce the
complexity of your
SpriteKit games.
And finally, we took you through
an in-depth case study on how
to build a custom focusable
control using our five star
rating control.
Now before we leave today,
we'd like to mention some
great online resources
to help you learn more.
Specifically, you
should definitely check
out the Apple TV
Tech Talks from 2016.
These cover -- these are
our videos available online.
They cover a wide array
of topics that are good
for people getting new to
the platform but also good
if you've had some experience
building for tvOS already.
Specifically, there's one
section, Focus-Driven Interfaces
with UIKit that goes
more in-depth into some
of the more basic
aspects of the Focus API,
some of the basic concepts,
an in-depth overview of some
some of the basic concepts,
an in-depth overview of some
of the parts of the API
that we didn't cover today.
It talks about some best
practices and also tools
and debugging support, which
we have available to help you
with building your apps.
You can find these
talks here at this URL.
And for more information
on today's session,
you can go to this URL to
get some helpful resources.
There are some other
related sessions this week
that you should check out.
If you're building games
with SpriteKit, definitely go
to the What's New in SpriteKit
session, where we also talk
about how to specifically
opt in your SpriteKit games
for focus support and then also
check out the What's New in tvOS
in Mastering UIKit
on tvOS sessions
to really take your UIKit
apps to the next level.
And of course, have
a great conference.
Thank you for coming today.