Dive into the latest additions to Game Center, Apple's social gaming network. Check out new capabilities for persistent game sessions and how they provide added flexibility for single-player, real-time multiplayer, and turn-based games. Learn about changes that streamline Game Center and a new way to send game invites and join multiplayer matches.
Thank you for coming.
My name is Megan Gardner.
I am a Software Engineer on the Game Center Team
and today we're going to be talking
about what's new in Game Center.
So if you don't know what Game Center is already,
Game Center is Apple's social gaming network.
It allows you, as developers, to define leaderboards
which your users can then submit scores to,
also define achievements that your players can earn.
We also have challenges which leverage both leaderboards
and achievements to add a multiplayer element
to your single player games.
We also have two multiplayer API's,
both real-time and turn-based.
And we ship all of these things on iOS, macOS, tvOS,
and this year we are announcing watchOS.
So what's new?
We've got a few new things this year.
First is we have a great new way of sending multiplayer invites.
Next we have big news for the Game Center app
if you haven't figured it out already.
We have a brand new API for persistent game sessions
that we're really excited about.
And we're also announcing Apple Watch support.
Now we don't have time to talk about Apple Watch
in this session, but if that's what you're interested in,
I really suggest that you go to the "Game Technologies
for Apple Watch" later this afternoon in this room.
So let's talk
about message-based multiplayer invites.
Now you can play with anyone that you can message.
Currently our multiplayer
for Game Center pretty much looks like this.
This is our GKMatchmakerViewController
and this is what most of you are using to set up your matches.
This is a built-in UI that we have done.
It allows your users to be able
to invite their Game Center friends as well
as do play now which is automatch.
Some of you have implemented GKMatchmaker
which is our programmatic API which allows you
to do your own UI and set up your own invites.
But if you've been using GKMatchmakerViewController,
it now looks like this.
This is our new integrated Messages View Controller.
You'll notice some differences.
There's no bubbles but that's not the most important part.
It now integrates directly in with Messages
which will allow your users to be able to send a message
to anyone in their Contacts and then be able
to play a game with them.
So let's see what this looks like.
This is the Multiplayer View Controller in Doodle Jump.
You can click Play Now
and automatch will work just as it has before.
However, we're more interested in seeing what happens
when we click Invite Friends.
So that will bring in this new Messages View Controller.
You can see we have this beautiful rich link here
that we've got.
We've got the little Doodle Jump icon in the corner.
I added a little bit of text that can tell your users
about what this link is going to let them do.
And this is all based on iCloud technology so all
of your users will need to be signed
into iCloud for this to work.
You can then start typing in the To field.
This will autocomplete to Contacts or you can just type
in a email address or phone number of anyone that you know
or anyone that you just met.
Or you can click on that Plus button which is going
to bring in the Contacts.
So these are all my Contacts
that I have Messages information for.
You'll also see that there's a Recents tab in the middle.
That is where your Game Center friends are going to be located
as well as anyone that your users have recently played
on Game Center.
And Nearby also functions the same way that Nearby has worked
in that it will be looking for players on local network
that are also playing this game.
So I'm going to click on Alisha,
invite my friend, Alisha, to play.
And then we'll click Add and it's going to fill her
in into that To field.
You can then, this functions just exactly as Messages.
This is basically Messages UI
so you're users can add additional text
and then it's going to send to all the players.
If I clicked on a Game Center player, their name is going
to show up in gray and they will getting a Game
They're not going to get some sort
of weird Game Center iMessage.
It will come in as a notification.
So if we click on that Send button, then that will send it
to Alisha and this is what it's going to look
like on Alisha's screen.
She can then tap the link to accept the invite,
and that will take her directly into the game,
and start connecting just like it would have
if she had tapped on the notification.
And the same functionality we'll have
if she did not have Doodle Jump, then it will take her
to the store where she can then download and play just
like she would be able to from a notification.
Now I said that there's nothing that you need to do
in order to implement this.
We have just replaced the View Controller
so if you have been using this View Controller,
then you've got this just straight out of the box.
As soon as iOS 10 is shipped all of your users will be able
to do this and invite anyone that they know.
They will no longer be limited to their Game Center friends.
However, we have one thing that you can customize
if you would like, which is this rich link image.
So you'll notice right here it's the Game Center icon currently.
If you would like to change that to be something else
that you feel more appropriately represents your game,
or more appropriately indicates that this is a gaming invite,
or a fun thing that people will want to click on, then you can,
all you need to do is add this file:
GKMessageInvite to your bundle.
And the same way that we will just pull that out if you wanted
to customize your notification sound, we'll just pull that out
and customize your rich link.
Notice this is the same rich link technology
that is being used for Safari and so it's used
to taking a wide variety of images.
So what does this mean for Game Center Friends?
Well, we don't need friends anymore
because we can play with anyone.
So we're freezing the friends list.
But you will still be able to see any
of the Game Center friends that you have
in that Recents Player tab.
And you can still pull the friends.
Friends still exists.
We're not deleting them.
They're still there.
But you won't be able to send, receive,
or respond to any more friend Requests.
And because of that,
GKFriendRequestCompose ViewController is
It wasn't really used that much anyway.
So what does that mean for the Game Center app?
Well, if you've downloaded The Siege,
you might notice some changes.
Well, what is the Game Center app used for?
In iOS 9 it was basically used
to manage your account, manage your friends.
You could browse your games list.
You could look at your leaderboards,
check out your achievements, view your challenges,
send challenges, and also view your turns.
Well, it turns out all of these things you can basically do
in other places in the system
and more importantly, in your app.
And so we have removed the Game Center app.
So where did we do all these things?
If you want to manage your account,
you can do that in settings.
If you want to manage your friends,
you can still do that in settings.
If you want to browse your games, we've got the App Store,
you can look at your Home screen.
You view your leaderboards, achievements, and challenges
If you're not using the View Controller,
you can also do your own UI.
If you're not presenting challenges or leaderboards
and achievements in your game, we strongly suggest
that you start doing that now.
And you can also view and take your turns from GKMatchmaker,
So we've removed the app.
Everything is really available in other places and,
more importantly, in your app.
We would love our users to spend, your users to spend,
more time in your app.
We've got the rest of the phone.
We don't need any more of their time.
And so we've removed the app.
Now let's talk about Sessions.
This is our brand new API and we're really,
really excited about this.
This is a brand new way to multiplay.
So Game Center Multiplayer, what does it look right now?
We basically have our two main API's
with real-time and turn-based.
Real-time will connect just two to four players.
Those connections will require like an immediate handshake.
If anyone drops from that connection,
then that whole connection will be lost.
You're just passing data back and forth.
And as soon as that match is over all of that data is gone.
Turn-based can connect to 16 players.
We have a very formal API for passing of turns
and also exchanges but you kind of really have
to follow those rules and you have to make sure your game
like fits within that structure.
And all games are stored on the Game Center server
until they are aged out.
So what is Sessions?
Sessions is our new iCloud-based multiplayer.
So we have this great generalized interface for saving
and sharing game data.
These are easily shareable little instances of data
that people can share with people
that they would like to play with.
It's a completely flexible game structure.
We don't impose anything on you.
You can do whatever you want.
And we have really stable, solid real-time streams
that you can set up within these sessions.
And this is going to allow you to play with anyone.
So what does a Session look like?
So we have two main items that we have.
We've got our game data.
It's probably one of the more important parts.
But also equally important is their players.
And really this is all that you need and all the basics
that you have to have to have a session,
is a player and some game data.
You can have multiple players which is useful if you would
like to play with other people.
We also have the ability to send messages between those players.
These messages will come in as Game Center notifications.
So you can have those messages being passed back and forth
between players or multiple players can send multiple
messages all at the same time.
Along with these messages we have the ability to badge.
So you can send those messages and also badge those players
to let them know that there's something within your game,
something within that session,
that they might want to take care of.
Now I only show four players here but we can actually have
up to 100 players in a single session which is a lot more
than we've been able to have before.
And we can have multiple different kinds of sessions.
So you can have small sessions that have one or two players.
You can have four players, 100 players, seven players.
Those players can be functionally grouped
onto different teams.
And you can have all of these sessions up
and your player can be in all of these different kinds
of sessions all at the same time.
We also have real-time streams so if you're in this session
and you would like to be able to pass data quickly back and forth
between your different players, then your players merely need
to set their connection states
and we will be setting these pipes up in the background
that will allow the players to be able
to start communicating with each other.
So, let's get into the actual code, the actual API
of what makes up a session.
So we've got a couple of classes.
We've got GKGameSession which is going to allow your players
to basically interact with that session data
as well as the other players.
We have GKCloudPlayer which is a player in a session.
We have GKEventListener which will help you know
when important things happen on any of your sessions
that your players are in.
And we also have GKGameSessionError
which will give you a little bit more specific errors
that you might encounter when working with Sessions.
So let's talk about GKGameSession.
So this is your main workhorse.
This is where almost all of the work is going
to be done per session.
It allows you to do basically everything.
You can create a session, leave sessions,
load and store your game data, share your sessions,
add your players, remove your players, see who's playing,
send your notifications, set and clear your badges,
join your streams, send data on those streams.
Basically everything you're going to be doing is going
to be interacting with GKGameSession.
Some more details about that.
With your game data you can store
up to 512 kilobytes of data.
This data is going to be stored in the user's iCloud
so it's not something associated with your game.
And the user is going to have it in their iCloud.
It will count against their iCloud limits.
And it's going to follow CloudKit conventions in terms
of who owns that data, how the data is shared, privacy,
and what happens when that data is deleted.
Messages and Badges, as I've said,
come in as Game Center notifications
and they're badged as such.
And badging is now going to be more directly controlled
by you, as the developer.
We'll get into that a little bit more but it's going
to be very clear where that badge number is coming from
and you should be able to understand why it is what it is
and change it to pretty much whatever you want.
And we also have these real-time streams
which basically leverage existing Apple infrastructure.
This is running on the same technology that runs FaceTime
as well as iMessage so it's really strong,
it's really stable, and it's built to carry a lot of data.
So if we want to make a session, what do we need to do?
Well, first we need a title,
something to describe the session.
Either you can define that or you can get that from your user.
You need your container ID which your iCloud container
that you set up with your app.
And also set up a container that can be used across multiple apps
so if you want multiple games to be able to access
that same data, say if you had your free version,
your pay version, or, you know, other different kinds
of versions of your game, they will still,
if you set that up correctly, they will still all be able
to access that same data.
And you can also set the max number of streaming players.
There's a hard limit of 16 players that can be
in that real-time stream but if you would like to make
that lower, or something different, then you can lower
that when you create the session but you need
to decide that when you create.
So once you've, so you just will call createSessionInContainer
with all of that relevant information
and that will give you a session
that you can start manipulating and using.
One of the first things you're probably going to want to do
with the session is be able to figure how
to load and save your data.
Any player that's in a session can access that data.
It's just one big blob that everybody plays with.
And there's a little bit of metadata provided
with that session that will help you avoid and resolve conflicts
which is last modified date and last modified player.
So you'll know who was touching it last and whether
or not it's important for you to save or if your data is more
than likely up to date.
So you can just call loadDataWithCompletionHandler,
that will pass you your data.
You'd also probably like to save your data.
As I said before, 512 kilobytes
but you can do whatever you want with that data.
It can be whatever will fit in that size.
So you'll call saveData with completionHandler.
If there is a conflict, if someone else has tried to save
in the interim, you will get an error and you will get
that conflicting data back.
And we'll talk a little bit more about that in a second.
Anytime someone does save data there's an Event Listener
that goes along with that.
So if you set up your Event Listener to listen
for a session player to save data, then you will know
when someone else has saved data and you will know
that you will more than likely will need to update
and resolve any conflicts local you have with that data.
So as I said, Save conflicts can occur.
And this will happen where two players who were basically going
to try to save data in about the same time.
Since there's no real formal turn passing it's very possible
that two players can be taking a turn at the same time
if that's how you design and implement your game.
So say we've got Players Two and Three and they both try
to save at the same time.
Well, one of them is going to win so I'm going
to say it's Player Two.
That means when Player Three tries to save they're going
to get an error and that conflicted data will
Now you are going to need to figure out how
to resolve this conflict.
Since we have no specific formalities
for what this data is we also don't know what the data means.
And so it's going to be up to you to architect your data
in such a way that it's going to be easy for you to figure
out what those conflicts are, resolve those conflicts,
and recall saved data in order
for that data to actually be saved.
If you do not recall saved data, your data will not be saved
and you need to continue to call saved data
until you return without a conflict.
And then everything will be up to date.
Everything will be the same for all your users
and you can continue forward.
And then everything will be grand.
We've talked about having multiplayers, well,
how do you get additional players into your session?
Any player that's in a session can invite other players
Basically you're going to be provided with a URL
that you need to get to someone else.
You can send this via iMessage, email, Twitter, Facebook,
print it out, paste it on a tree --
that's probably not the best way.
But as long as you can get this URL to other people
and they can click on it, then it will be able
to be added to that session.
The easiest way to do this is through the share sheet
because it just pops up right there
and you can send off a message.
And that's probably the easiest way to do that.
So if like the Player One, if they pull the URL from their,
from the session, they set up an iMessage with that share sheet
to send to Player Two.
They've added a little bit of text, "Hey,
want you want to play with me?"
It'll come out as this iCloud URL.
It will be sent to Player Two, they will click on it,
and as soon as they click on it Player Two is added.
So in order to get the URL you just call getShareURLWith
It will give you the URL
that you can then do whatever you want with.
And then anytime a player is added
to a session the Event Listener didAddPlayer will be called.
And that will let you know
that someone else has joined your session and be able
to proceed with your game accordingly.
So we've been talking about players
so what exactly are they?
Well, we've got GKCloudPlayer.
This is different than the GK Players
that you've been dealing with before.
GKCloudPlayer is only for, to be used for Sessions.
It basically has two pieces of data, a player ID that is unique
to your app as well as the display name,
that is what the user will have
as what they want they name to be displayed.
This is not a GKPlayer object at all.
If you try to use this for a leaderboard, for achievements,
for other multiplayer, for anything else, it will not work.
So please don't do that.
Everyone will be very disappointed.
So how do we get our Cloud Players?
Basically you can get your current signed in player.
Most of the things in Sessions basically are going to be called
from your current player though there's not a whole lot of need
to make sure that you have the player,
that you are then saying, "Oh,
this player is saving this data."
All that's handled for you in the background.
But you might be interested to know basically
like who owns this session?
So you might want to know if the session is being deleted,
if other player owns it,
then that will delete the data for everyone else.
And you also might want to be able to clear your badges,
send messages, be a little more aware of that.
You can also get any of the other players that are
in the session, it's just a property on that session.
And that's the best way that you're going to need to be able
to send those messages to those other players,
especially setting and clearing badges.
So speaking of messages and badges, let's talk about that.
These messages, we say messages but they're coming
in as Game Center notifications.
As I said before, all players can send messages
at any time to any other player.
Those messages are easily localizable.
You can also send a little bit of data along with that message
if there's any sort of relevant information that you might want
to pass to the other players about what this message is about
or what they might want to be looking at specifically.
And you can also optionally badge the message recipient
so anyone that gets this message can also receive a badge
as well as that message.
So what does the code look like?
You've got all these arguments, who to send it to, whether
or not you would like to badge those players.
And the Event Listener that is called is session
And that will be called any time a notification comes
in to let the player know that something has come
in that they might want to be aware of
or might want to deal with.
So I've said badges can be included with these messages.
So basically anytime you send a message you can basically turn
that badge state on for that player.
You've got one badge per session so basically it means
like there's something you need to deal with or there's not.
And these badges can be set and cleared at any time.
So if you send a message and then you're like, "Hey,
I need some help with this thing that we're doing in the game,"
and then no one shows up you can, you know,
clear those badges and be like, "Never mind.
I didn't want to talk to you anyway."
And so that you can keep all
of that badge data relevant and up to date.
The app icon will show the overall tally
so if you've got three sessions and all of them are badges,
that app icon will say three.
If you have one, you know,
only one of them is badge, it will say one.
We could aggregate that for you but based off of the,
what is set in that session it should be very clear
where that badge number is coming from.
So let's talk about managing these sessions.
So we've made a session.
We've saved it.
We've loaded it.
We've loaded the data.
We've sent it to some players.
Your user has turned off your app.
They've done some other things.
You've come back.
You want to load those sessions and make sure
that you've got all the relevant data
so that they can start playing again.
So the first thing you'll want to call is Load Sessions.
loadSessionsInContainer, that container,
that same app container from the beginning
that you made the session in.
This will load the bare bones information for all the sessions
that your local player is a part of.
Then based off of that data you're going to want to look
and figure out which session you're going to want to load.
That session has two main pieces to identify it.
One is that title that you gave us but the title is not unique.
You can make it anything that you want.
And so that's not enough to be able to just load a session.
Upon creation of a session we will give you an identifier
and that is what you will need to use in order to load
that specific session.
and that will give you all the information
for the session including everything that you will need
to do in order to start loading that data, sending messages
to other players, and continuing on with your game.
You also might want to delete a session.
If you call removeSessionWithIdentifier,
that's the same identifier that we just talked about,
if the player does not own the session,
it will merely remove them from the session.
It will not actually delete any of that data.
However, if you're deleting a session
that that player created, then it will delete that data,
not only for that player,
but for everyone else in that session.
And that may be one of those times
that who your local player is, figure out if they are going
to be doing that to everyone, and maybe send,
alert the user that, "Hey, you're deleting this
for everyone," so that they know what they're doing.
At any time a player is removed the Event Listener will be
called didRemovePlayer so that you'll know
that someone has left and that you can continue
to update your game accordingly.
So let's talk about Game Session Streams.
So this is the real-time element of Sessions.
Everything else up until this point has kind
of sound pretty turn-based.
You're passing messages.
We also have the ability to have real-time elements to your game.
So Game Session Streams, you are going to be able to connect any
of the players that are currently in that session.
So everyone who is in that session, if they would
like to start sending data to each other,
that is how you're going to do it.
You can basically see the status of any other players
that are in the session.
You can send data to all the players that are
in the connection that you've set up.
And you will be able to add and drop players at any time
without having to restart that connection.
So you can someone join in and like two people can be playing,
third person wants to come in and join, you don't have
to reset everything up.
As soon as they start they'll start receiving data.
They can start sending data.
You don't have to do any handshakes for handling all
of that in the background for you.
So how do we set these connections up?
Basically you just need
to set the connection state for that player.
So you would just call setConnectionState
This can fail for a number of reasons but one
of the reasons could be if the max players
for that session has already been reached.
So if this is the 17th player who is trying to join
that stream and you've got that max 17 set,
then this will actually fail and they won't actually be able
to join into the stream.
You can see whether the players are set with a specific state,
basically the states are connected and disconnected
so you can see how many other players are currently connected
and who they are.
And anytime a player either changes that connection state,
either connects or disconnects,
the Event Listener session player didChangeConnectionState
will be called.
And so you can know whether or not that is changed
and how many people you are currently playing with.
Once you set up the connection then you're going to want
to probably start sending data.
So all of the data is going to be sent to all
of the connected players.
You can send this either reliably or unreliably,
just the same as our real-time API now.
Whether or not it's more important to make sure
that those players get that data or more important to make sure
that they're getting the data as fast as possible.
And any time data is sent the Event Listener
didReceiveDataFromPlayer will be called and you'll be able to get
that data and update your game locally, and continue
on with playing your game.
So that's all like the basic bones of what makes up sessions.
So let's talk about some examples
of what this actually really looks
like when you're actually making a game.
So first basically you've got, you know,
your basic turn-based game.
So you've set up your session.
You've got your game data.
You've added a few players.
Maybe it's Player One's turn.
They're going to start by figuring out what their turn is
and they're going to save that data.
That data can then be loaded by Players Two, Three, and Four.
Message Player One can then send a message to Player Two,
sending it that badge and saying,
"Hey, it's your turn now."
Maybe you would like to do that.
Player Two can load up their game, start playing,
figure out what they would want to do with that new data,
take their turn, save that data,
and then pass the turn on to Player Four.
Since there is no specified way
in which these turns can be passed that's up to you.
You can pass it from One to Two, Two to Three,
Four to One, whatever you want.
There is no specified way
in which these turns can be passed and, frankly,
we don't know what you're doing.
So you pass the game on to Player Four.
They get to take their turn and continue on.
So you've got all the elements that you need
for a really basic turn-based game.
You can also do a real-time game.
So you've got all of your players set up.
You can then basically have everyone turn
on their connection states.
As soon as these connection states are turned on we will set
up the pipes in the background to allow them
to communicate with each other.
And as soon as all of those are set
up then your players can start sending data to everyone else.
And then this data will be just sent as long
as these connections are available.
And then with sessions, if there's any sort
of information you would like to be able to store at the end,
such as, you know, who won, or rankings,
or anything for this particular real-time game,
you do have that ability to have a little bit more
of a persistent data that you might want
to save with that session.
So those are your real basic examples.
But the real power session comes in in being able
to do much more complicated games.
So say you've got a game session.
It's a turn-based game but you want to do a little bit more
of a complicated turn.
They've got a game.
It's got some trading card elements
so when it's the player's turn you might be able
to trade cards, maybe brick for sheep or something.
And so the things that you might be able to accomplish
with table talk on an actual board game you can now more
easily accomplish with sessions.
So say it's Player One's turn and they want to trade
with the other players and so they send out a message and say,
"Hey, I'd like trade brick for sheep.
So you can send that message.
You can send a little bit of data with that message
to let the users know, "Hey, this is what I want,"
and send it out to everyone.
Say Player Four is like, "Oh, yeah.
That sounds really good.
You know, I'll take that trade," or, "Yeah, well, you know,
that doesn't work for me.
How about wheat for sheep?"
or something else.
So they can send a message back to Player One, badging them
and saying, "Hey, this is, I either, I'll accept your trade
or I have a different trade."
You can send that message back and forth,
figure out what you want to do.
As soon as Player One decides, "Okay.
Well, I'll take that trade," or, "I won't take that trade,"
they can their turn, unbadge everyone else,
and save their data, unbadge themselves,
and then pass the turn on to Player Two.
We also have the ability to more easily join
into multiplayer games
that might be a little bit more complicated.
So say you've got a multiplayer game that's a little bit more
like a King of the Hill type stuff.
You've got all these people in session but you only want two
of them to be able to play at a time.
So you're going to start up your session.
You've got Players One and Two.
They're going to turn on their connection state.
They're going to join into a game and they're going
to pass their data back and forth.
They're going to have a little head-to-head,
a little one-on-one, and fight.
And one of those players will be eliminated.
In this case let's say Player One.
And then Player Two will go on and then play
with the next person in line.
You don't have to stop your game in any way.
You don't have to set up any sort of connection screen.
As soon as Player Three sets their connection state then you
can start sending that data back and forth to Players Two
and Three immediately and they will be able
to have their little bout, see who wins.
This time [inaudible] and then Player Four can then come
in and join in the fray.
They can make that connection and continue on.
And you can continue on with this,
continuing to do any sort of round-robin.
If you've got like 100 players,
you can go through all 100 players.
And just continue to have a little King
of the Hill style fight.
And then you can store that data to your game data
that will allow to have a little bit more persistent rankings
and a little bit more persistent [inaudible] among the people
that are in this session.
Another situation that we might run
into is assisted single player.
So say you've got a single player game.
You're using Sessions to basically store your data
which is totally fine.
You can absolutely do a single player game with Sessions
and basically use this as a way to store your data
and send your data so that all of your data can be updated
across all of your devices very easily.
But say your player is having a little bit of a hard time.
They've been playing this game for a little while.
Then they can't get passed this level.
They're having a really hard time.
Well, if you implement your game as such,
then Player One can then share their game with another player.
And so they can bring in Player Two.
And then you can either add some elements
that will allow Player Two to help Player One
through that level, through some co-op methods,
or you could even just allow Player Two to just play
that level for Player One so that they can get past
that really sticky point in your game, allowing Player One
to have a little bit more enjoyment.
So Player Two can come in, say,
do whatever you would like to let them do.
Save that data, so the game data.
And then they can lead themselves, removing themselves
from that game and Player One can continue on playing
that game just as if Player Two had never actually even
So that is Game Sessions.
This is going to allow you to be able to basically play
with anyone, anyone that has an iCloud account you can
You don't need to be their friend in any sense of the word.
So much more flexible game structure that is going
to allow you, as developers, to be able to set up your games
in whatever manner you would like.
We have really, really simple multiplayer connections.
They are really easy to set up, really stable.
They allow for lots of data to be passed back and forth.
And we're really excited
to see what new possible game styles you're going to come
up with because of the power of Sessions.
Because of this mixing of turn-based
and real-time elements for these games we're really excited
to see what you're going to come up with.
So that's what's new in Game Center this year.
We had our new message-based multiplayer invite
which are now going to allow you to play
with anyone that you can message.
We have removed the Game Center app.
We have those persistent game sessions
that we just talked about.
And we have also announced Apple Watch support.
If you would like any more information on this session,
you can go to this link.
We are session number 611.
And we have a few related sessions
that you might be interested in.
We have the "Game Technologies
for Apple Watch" later on in this afternoon.
We've also had several sessions earlier this week
that you can go and watch the videos for, and several others,
even more than what's listed here.
Thank you for coming and have a great WWDC.
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.