Transcript
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
>> Good morning and
welcome [applause].
Thanks a lot for coming.
So my name is Demijan Klinc
and in this session we'll talk
about nearby networking
with Multipeer Connectivity.
So what is Multipeer
Connectivity?
Well, Multipeer Connectivity
is a brand new framework we're
shipping in iOS 7 that
facilitates discovery of
and communication
with nearby devices.
It abstracts complex
programming --
network programming aspects from
you and enables you to build --
to easily build communication
sessions with nearby peers,
where they can exchange
data with each other.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So essentially, we're looking
at a situation like this one,
where we have multiple iOS
devices in close proximity
of each other and what they
want to do is they want
to establish a communication
link and they want
to exchange data
with each other.
Now this here is
a very simple --
simplistic case and the
framework also supports much
more complex setups.
Like this one, for instance,
where we have many iOS devices
that participate in multiple
sessions at the same time.
So what are the use cases
for this technology?
Well, let me -- let
me name a few.
Interactive tutoring,
collaborative document
and photo editing, file
sharing, coordination
across multiple devices,
and sensor data aggregation.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Of course, these are
just a few examples
and the playing field is wide
open for you guys to explore.
We can't wait to see
what you come up with
as you start playing
with the framework.
Under the hood, Multipeer
Connectivity supports
connectivity using
classical Bluetooth
and infrastructure Wi-Fi.
And, in addition, and we're
very excited about this,
in iOS 7 we're adding support
for peer-to-peer
Wi-Fi Networking.
[ Applause ]
So peer-to-peer Wi-Fi Networking
will enable your iOS devices
to communicate with each
other using Wi-Fi technology,
even if they're not
connected to an access point
or if they're connected to
different access points.
So we think this will
bring nearby networking
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
on iOS to a whole new level.
We're very excited about this.
So what are the features
of the framework?
So as I just mentioned,
we support multiple
wireless technologies.
We have interface selection.
So by that I mean that the
framework will choose the best
wireless technology for you
under the hood, so that you --
so your users get the best
networking experience.
We will give you
convenience and --
convenience, discovery,
and invitation UI.
So we'll give you tools
that will make it very,
very easy for you to discover
who is nearby and mechanisms
to invite nearby peers and have
them connect into a session.
Then, once you're in a session,
we will give you the APIs
to send data and will
support message-based data
and stream-based data.
Also, we have built-in
support for security as well,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and specifically,
we'll give you support
for authentication
and encryption.
Now this brings me to
the agenda for today
and we'll have two bigger parts.
In the first part, we'll
cover the essentials,
and in the second part, we'll
cover some advanced topics.
In the essentials, we'll
look at two phases.
First, we'll look at
the discovery phase
and the discovery
phase will be the phase
where you're discovering
who's nearby
and you're inviting nearby peers
to a session, so basically,
everything that happens before
the peers are successfully
connected with each
other in a session
where they can exchange data.
Then we will cover the session
phase and there we'll assume
that everybody's
already connected
and we'll see how you can
have them exchange data
with each other.
Once we're done with
the essentials,
we'll look at some
advanced topics.
Specifically, we'll look
at programatic discovery
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and we'll look at security.
All right, so let's
dive in, the essentials.
First I want to define some
terminology that we will use
in today's talk and I
want to start with nearby.
So what is nearby?
For a particular device, another
device will be called nearby
if the two devices can
communicate directly
with each other using one of the
supported wireless technologies.
Peer. A peer will
be a nearby device.
Advertiser.
An advertiser will be a device
that makes itself
discoverable to other devices.
Similarly, the act of
advertising will be the act
of making oneself
discoverable to other peers.
And lastly, browser.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
A browser will be a
device that is searching
for other nearby devices.
And similarly, the act of
browsing will be the act
of searching for nearby devices.
Okay. So with that established,
let's jump into the
discovery phase.
And to start, I want to go
with you through the flow
of the discovery phase.
So let's assume I'm
running an app
that uses Multipeer
Connectivity and I want to see
if there are any peers nearby.
So I bring up my browser, my
browser UI that is supplied
by the framework, and on
my browser UI I can see
that I'm searching
for nearby peers.
There is currently
no one around.
A few moments later, Jeff
comes by and I will see
that Jeff is nearby on my UI.
Then I will also
have Gabe join us
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and moments later I also
see that Gabe is nearby.
So what I want to do now is I
want to invite Jeff and Gabe
into a session so we can start
exchanging data with each other.
How I can do that?
Well I can invite them simply by
tapping on their names on my UI.
So let's start with Jeff.
I tap on Jeff and as I do
so an invitation will
be sent out to Jeff.
Then I will tap on Gabe
and an invitation will be
sent out to Gabe as well.
When Jeff receives
the invitation,
we will display an alert
for you that notifies Jeff
that I want to connect to him.
At this point, Jeff has
to decide whether he wants
to accept or decline
my invitation.
Similar will happen to Gabe.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And let's now assume
that both Jeff
and Gabe are willing
to connect to me.
So they will tap on
accept and as they tap
on accept an invitation
response is sent back to me
and we start connecting.
On my UI, when we successfully
connect to each other,
I will see that I have
connected to Jeff and Gabe
and the Done button on the --
in the upper right
corner becomes tappable.
So I can press the Done
button to dismiss the UI
and start exchanging
data with Jeff and Gabe.
So that was the flow
of the discovery phase.
Let's now see how you guys can
make this possible in your apps.
This slide here shows
you the type of objects
that you will have to use to set
up the advertiser
and the browser.
So let's start with
the advertiser.
What are the tasks
of the advertiser?
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Well, as we said, the advertiser
has to make itself discoverable
to other nearby peers.
If an incoming -- if
an invitation comes in,
the advertiser has to display
that invitation to the user.
And when the user decides
whether he wants to accept
or decline an invitation,
the advertiser has
to handle that response.
Also, if the response was
positive, it has to hook
up the nearby peer
into a session.
So these are the tasks
of the advertiser.
In code, what you
have to do is you have
to identify yourself first or
identify your device first.
And for that, we give you
a class called MCPeerID.
To instantiate that
class, you will have
to pass it one parameter,
an NSString object,
which will specify the name that
you want to use for your device.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
I want to tell -- I want
to note here that the name
that you specify here
will also be the name
that the browser
will see on their UI.
So I want to encourage you
to keep this name short
so we won't have to
truncate it in the UI.
Next, you will have to
instantiate a session object.
The session object
is of class MCSession
and it accepts one parameter,
which is the MCPeerID Object
that we just instantiated
earlier.
And also, the MCSession object
has a delegate and you'll want
to set that delegate
to get notified
of MCSession-related events.
Lastly, you'll want to use the
MCAdvertiserAssistant object
and the MCAdvertiserAssistant
object is instantiated
with three parameters.
The first one is a service type
and that's an NSString
parameter.
A service type identifies
the type of session
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that the advertiser
wants to participate in.
So I want to say that the
service type is a Bonjour
service type and I
encourage you to register it
as such once you've decided
which service type
you want to use.
The second parameter is the
discovery info and we'll talk
about discovery info
in more detail later,
so let's just set
that to nil for now.
The third parameter and the last
parameter is the session object
that we instantiated earlier.
Once we've instantiated
the advertiser assistant,
all we have to do is start it
by calling the Start method.
And that's it.
We're done setting
up the advertiser.
So let's take a look
at the browser now.
So what are the tasks
of the browser?
Well, the browser is
searching for nearby peers
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and as it finds nearby peers,
it needs to present them
to the user for you.
Once a user decides which
peer they want to invite,
the browser has to send an
invitation to that peer.
And when a response comes
back, the browser has to handle
that invitation and in case
the response was positive,
it needs to hook up that
peer into a session.
So these are the
tasks of a browser.
In code, the browser's
setup is very similar
to the advertiser's setup.
The first two steps
are exactly the same.
You need to instantiate an
MCPeerID object and you need
to instantiate an
MCSession object.
Then the last step is
to instantiate the
MCBrowserViewController object
and you have to pass
it two parameters.
The first one is a service
type and that service type has
to be exactly the same as the
service type that you specified
for the advertiser; namely,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
a browser will only
see those advertisers
that have the same service type.
The second parameter
is the session object
that we just instantiated
and which you want the
browser view controller to use.
Next, you will have to set
the delegate on the browser
to get notified of
browser-related events.
And when you set the
delegate, you're ready
to present the browser
view controller to the user
and as you do so, we will
start browsing for you
and the rest will
be user driven.
[ Silence ]
So at this point,
we are presenting --
the framework is
presenting the UI for you
and the user is choosing the
users to invite and it's waiting
for invitation responses
to come back.
Once the nearby peers have
successfully connected
into a session you
will see that the --
or the user will see that the
Done button becomes enabled.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And when the user
presses the Done button,
you will be notified
via a delegate method
browserViewControllerDidFinish:.
Now inside that method, you will
have the opportunity to prepare
for the session and you have
to dismiss the browser
view controller UI.
So that's, again, the overview
of classes that you have to use
to set up the discovery phase.
And now I want to tell you a
bit more about how do you know
that the session objects
connected with each other
and how do they even know
who they want to connect to.
Well, let's assume we have
a browser view controller
on one side and the advertiser
assistant on the other side set
up and as peers get
found and lost,
the browser view controller
and the advertiser assistant are
communicating with each other.
Now the browser's session object
will know who the browser wants
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to connect to when the user
taps on someone to invite.
So when an invitation
is sent out.
The advertiser's
session object will know
who the advertiser
wants to connect
to when the user
accepts an invitation.
When that happens, the two
session objects will attempt
to establish a communication
link with each other
and once they succeed, you
will be notified via a session
delegate method
peer:didChangeState:.
So let's take a look
at this delegate method
in a bit more detail.
You can see it here
on this slide,
session:peer:didChangeState:.
The second parameter will
give you the peer ID object
of the peer who just
changed state
and the state will tell
you what the new state is.
If the connection was
successfully established
between the two sessions,
the state will
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
by MCSessionStateConnected.
And if something went wrong
during the connection process
or if the advertiser
declined an invitation,
the state will be
MCSession Not Connected.
So to summarize, the
discovery phase is really,
really easy to set up.
All you have to do is
instantiate an advertiser
assistant and start it.
Then you have to instantiate
the browser view controller
and present it to the user.
And the rest of the process
will be entirely user driven.
All you have to do is wait
for the session callbacks
to tell you when the session
has successfully connected
to your nearby peers.
Okay, so let's move on
to the session phase now.
Now we assume that we have
multiple nearby peers connected
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
with each other and they
want to exchange data.
So let's take a look at
how you guys can do this.
We provide three sets of send
data APIs for you: messages,
streaming, and resources.
So let's start with messages.
By message I mean a chunk
of data, any chunk of data,
with well-defined boundaries.
So it's very clear
where the message ends,
where the message starts,
and where the message ends.
So if you send a
message in one call,
you will also receive
a message in one call.
We provide two different modes
to send messages for you.
The first one is the reliable
mode and you will want
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to use the reliable mode for
application-critical data.
If you send a message
in the reliable mode
and something happens to
the message along the way,
for instance, if
it gets dropped,
the framework will
retransmit the message for you.
Also, if you send
multiple messages in a row,
the framework will make
sure that the recipient
of the message will
get them in order.
Alternatively, you can
use the unreliable mode
and we encourage you to
use the unreliable mode
for time-sensitive data.
So if you use the
unreliable mode,
the framework will make best
effort to deliver your messages
as soon as possible
to the recipient.
So the -- so with the
smallest possible latency.
However, you should know that
if something happens to messages
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that were sent in the unreliable
Mode, we will make no attempts
to retransmit that
message for you.
Also, if you send
multiple messages in a row,
we give you no guarantees that
they will be delivered in order.
So these are the two modes,
reliable and unreliable.
Let's take a look at the APIs
that you will have to use.
It's really, really simple.
To send a message, you
will invoke a method called
sendData:toPeers:withMode:
and error:.
The first parameter will be
where you place you message
and that's an NSData
object, so you will have
to encapsulate your
messages into NSData objects.
The second parameter is an
NSArray and you will have
to pass it an array of peer
IDs that designate peers
that you want to
send a message to.
If you want to -- if you want
to get a handle of all peers
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that are currently
connected in your session,
you can do so by invoking
connectedPeers method
on your session object.
The third parameter
will be the mode,
which we discussed earlier,
either reliable or unreliable.
And the fourth parameter
will be an error parameter.
It's an output parameter that
the framework will set for you
in case something goes wrong
when you make the call.
I want to stress here that
send data returns immediately.
It's a nonblocking call, so
it will return immediately.
It won't wait until
the data is delivered
or something like that.
On the receiver's side,
when the message comes in,
the receiver will be notified
via a session delegate method,
session:did
ReceiveData:fromPeer:,
and the second parameter
will be an NSData object,
which will be exactly
the same as the one
that was specified
by the sender.
And the third parameter
will be the peer ID
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
of the sender of the message.
So it's that simple
to send messages.
Next, let's take a
look at streaming APIs.
To start a stream
with another peer,
you'll have to call the method
startStreamWithName:toPeer:
and error:.
So in the first parameter you
will have to specify a name
for the stream that
you are trying to open.
And this name is going
to be an NSString object.
Second parameter will be the
peer ID of the peer you want
to send -- you want
to stream data to.
And the third one
will be like before,
an output error parameter
that we will set --
the framework will set, in
case something goes wrong.
Just like the sendData:
method, startStreamWithName:
is nonblocking and it
will return immediately.
As it returns, it will give
you an NSOutputStream object
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that you will be able to use to
stream data to the recipient.
On the other side, when
the streaming request comes
in at the receiver, the receiver
is notified via this delegate
method, session:did
ReceiveStream:WithName:
and fromPeer:.
The second parameter will
be an NSInputStream object
that the recipient can
use to receive data.
The third parameter will
be the name for the stream
that the sender specified.
And the fourth parameter will
be the peer ID of the sender.
Once both sender and the
recipient have a handle
on the stream objects, they'll
have to set the delegate
on them, they'll have to
schedule them in a run loop,
and they will have
to call open on them.
Of course, they will also have
to implement NSStringDelegate
methods
to send and receive data.
So that was streaming.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And lastly, let's take
a look at resource APIs.
So we provide support for
sending resources for you
and we provide support
for sending files
and for sending web URLs.
So let's see how you guys
can implement that in code.
To send a resource to someone,
you will call a method
sendResourceAt
URL:withName:toPeer:
and you will have
to pass a completion handler.
The URL will be the URL of the
resource that you want to send.
This will be either
a file or a web URL.
If you specify a web URL here,
the framework will go ahead
and fetch the contents
of that URL
and send it to the recipient.
The second parameter will be an
NSString, which will be the name
for this resource transfer.
The third parameter will be
the peer ID of the recipient.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And the fourth one will be
the -- a completion handler,
which the framework will call
for you once the resource has
been successfully transmitted
to the recipient.
Also, the framework will
call the completion handler
in case something goes wrong.
So in both of these cases,
the completion handler
will be called.
Like the previous two
methods, sendResourceAtURL:
is nonblocking and it
will return immediately.
As it returns, it will pass
to you an NSProgress object.
NSProgress is a new class
in Foundation in iOS 7
and it will enable you
to query current progress
of the transmission.
Also, it will give
you the ability
to cancel the transmission
if you desire to do so.
So let's take a look at what
happens on the recipient's side.
When the resource gets --
when it starts receiving
the resource,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
the receiver's delegate
method will be notified via
didStartReceivingResource
WithName:fromPeer:withProgress:.
The second parameter will be a
name that the sender specified.
FromPeer: will be
the ID of the sender.
And withProgress: will
be an NSProgress object
that the recipient can use
to monitor current progress
or to cancel transmission.
And when the framework finishes
transmitting the resource,
the receiver's delegate
will be notified via
didFinishReceivingResource
WithName:fromPeer
:atURL:withError: method.
Again, the second
parameter will be a name.
The third parameter will
be the ID of the sender.
The fourth parameter
will be the URL
where the framework saved the
resource locally on the device.
And the last parameter
will be an error
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that the framework will set
in case something goes wrong.
So again, this callback
will be called in two cases,
if the resource has been
successfully transmitted
or if something went wrong.
In that case, an error
parameter will be set for you
so that you will know
that something went wrong.
So these are the APIs to send
data that we provide for you.
We have messages,
streaming, and resources.
And with that out of the way, I
want to tell you something cool
that Multipeer Connectivity
provides for you at no cost.
You don't have to do anything
to make this functionality
possible in your apps.
So let's assume we
have three devices,
just like on this slide, that
want to connect to each other
and exchange data with
each other [coughing].
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Okay, so let's also
assume that the device
on the left has Bluetooth
on and also has Wi-Fi on.
The device on top will have only
Bluetooth on, so Wi-Fi's off.
And the device on the right will
have Wi-Fi on and no Bluetooth.
So you would think that the
device on top and the device
on the right cannot
communicate with each other
because they don't share
a common interface.
Bluetooth and Wi-Fi
cannot communicate directly
with each other, but Multipeer
Connectivity has infrastructure
built-in that will -- that will
enable these devices to be aware
of each other, even if they
don't share a common interface
and this will be done
through the device
that has both interfaces
available.
[ Applause ]
So we will make sure
they're aware of each other
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and if the device on the
right wants to send messages
to the device on
top we will do --
do so for you through
the device on the left.
So they will be able
to seamlessly communicate
with each other.
So we think this is really cool.
To disconnect from a
session, all you have to do --
to disconnect yourself
from a session all you have
to do is call the
disconnect method.
And in case someone else
disconnects from a session,
you will be notified via
a session delegate method
session:peer:didChangeState:,
which we're now familiar with.
The state will be
MCSessionStateNotConnected
if someone disconnects.
So the session phase summary,
we've described three sets
of data -- of send
data APIs for you.
We have support for messages
and we support reliable
and unreliable mode.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
We have support for streaming.
And we have support
for sending resources.
And that's really it [applause].
So that's all you need to
do to make this possible
and have multiple nearby
peers connect with each other
and exchange data
with each other.
It's really that easy.
In the discovery
phase, all you have
to do is instantiate
an advertiser assistant
and start it.
The -- on the browser side,
you have to instantiate
the browser view controller
and present it to
the user and the rest
of the process will
be entirely driven
by the user and the framework.
Once your peers connect into
a session, you can use one
of the send data APIs
to send messages,
stream data, or send resources.
And that wraps up
the essentials.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
[ Applause ]
So let's move on and let's take
a look at some advanced topics.
I want to start with
programatic discovery.
So what programatic discovery
will enable you to do,
it will enable you to handle
events like found peer,
lost peer, and actions
like sending invitations,
responding invitations.
It will make it possible for you
to handle these things
programatically.
So this will give you a lot of
flexibility and will enable you
to build custom UIs for
the discovery phase,
if you choose to do so.
So let's take a look
at how you can do this.
To set up an advertiser,
you will use an
MCNearbyServiceAdvertiser object
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and you will have to
pass it three parameters.
The first one will be a peer ID
that we're now familiar with.
And the second one will be
discovery info that I want
to cover in a bit
more detail now.
So discovery info is
an NSDictionary object
that you can set and it's going
to be a set of key-value pairs.
This set of key-value
pairs will be added
to the advertiser's
Bonjour TXT record.
That means that when the
browser sees this advertiser,
it will see this
information along with the --
with the fact that
it discovered it.
The third parameter
is a service type
and we all know what
service type now is.
You'll have to set a delegate on
the advertiser to get notified
of advertiser-related events
and to start advertising
you will call
startAdvertisingPeer method.
On the browser side, you will
need an MCNearbyServiceBrowser
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
object and to instantiate
it you will need
to pass it two parameters.
First one will be the peer ID
and the second one will be
a service type, which again,
I would like to emphasize
that the two service types,
the one that the advertiser
specifies and the one
that the browser specifies
they need to be the same,
otherwise they won't
see each other.
Also, you will need to set
the delegate on the browser
and to start browsing,
you will have
to call startBrowsingForPeers
method.
So let's now go through
the flow if you choose
to do programatic discovery.
We have three devices here.
The device on the left
will be the browser.
The device in the
middle and the device
on the right will
be advertisers.
When the browser
discovers an advertiser,
the browser's delegate
method will be notified via a
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
foundPeer:withDiscoveryInfo:
callback.
This same callback will be
called every time an advertiser
is discovered.
So let's take a look
at how it looks.
This is the callback
browser:found
Peer:withDiscoveryInfo:.
The second parameter will
give you the peer ID object
of the peer that
just got discovered.
And the third parameter
will be the discovery info
that we talked about before.
So if advertiser
set discovery info,
the browser will get copied
version of that dictionary once
that callback is called.
In case a peer will
get lost, for instance,
if it goes out of
range of the browser,
then you will get
notified via a delegate
method browser:lostPeer:.
So now let's assume that the
browser knows which peers are
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
around and you want -- what
you want to do now is you want
to send invitations
to these peers
to start communicating
with them.
Well, to send an invitation,
a browser will have
to call invitePeer:toSession:
method.
And as it does so, an invitation
will be sent out to that peer.
When the advertisers -- when
the advertiser receives the
invitation, the advertiser's
delegate will be notified via a
delegate method
didReceiveInvitationFromPeer:
and the advertiser will be
passed an invitation handler.
Same thing happens when we
want to invite the advertiser
on the right and when it gets
the invitation, it gets notified
with the same callback method.
And at this point, the
advertiser will probably want
to consult the user whether
the user wants to accept
or decline an invitation.
And once it does so, once we
know whether an invitation is
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to be accepted or declined,
the advertisers have
to call the invitation handler
that was just passed to them.
So assuming that the answer was
yes, you will have to specify
that answer in the
first parameter of --
of the invitation handler.
And the second parameter will be
the session object that you want
to use for that invitation.
So in code, the invite
function looks like this,
invitePeer:to
Session:withContext:
and timeout:.
The first parameter will
be the peer ID of the peer
that you want to invite.
The session -- the second
parameter will be the session
that you want to use
for that invitation.
And the third parameter
will be context.
This is an NSData
parameter that allows you
to pass some context
along with the invitation.
Timeout here is a
value in seconds,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
which tells the framework how
long the browser is willing
to wait for the invitation
response to come back.
When the advertiser's --
when the advertiser
receives an invitation,
you will be notified via
this delegate method,
advertiser:did
ReceiveInvitationFromPeer:with
Context: and invitationHandler:.
So the second one will
be the peer ID of the --
of the sender of the invitation.
The third one will
be the context
if the sender specified
some context.
And the fourth one will be a
block, an invitation handler
that the advertiser will have
to call once it knows
whether the invitation is
to be accepted or declined.
So let's take a look
at one possible example
of how you can implement
this delegate method
on the advertiser.
And let's assume that once
an invitation comes in,
you want to present
an alert to the user
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and you want the alert
-- the user to press --
to tap Accept or
Decline to decide
or to notify the
framework of the decision
or you of the decision.
So first thing you want
to do is you want to copy
and store the invitation handler
because you'll need it later
when you find out from the
user what it wants to do.
Then you have to instantiate
a UIAlertView and you have
to specify the title and message
for the view -- for
the alert view.
And you want to specify
what kind
of buttons you want on there.
So let's assume they're
Decline and Accept.
Then you're ready to
show the alert view.
Once the user taps on
either Accept or Decline,
you will be notified
via a delegate method
alertView:clickedButtonAtIndex:
and what you want
to do first is retrieve
the invitation handler.
Then you'll want to extract
what the user's decision was,
whether to accept or decline.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And once you know that,
you'll want to call
the invitation handler
and passing it --
the response first
and then the session
object that you want
to use for that invitation.
So again, let's take a look
at how you arrive to the point
where two session objects
are connected with each other
if you choose to do
programatic discovery.
So as peers get found
and lost, browser
and advertiser communicate
with each other.
The browser's session object is
notified of which peer you want
to connect to when you called
invitePeer:toSession: method.
And the advertiser's
session object is notified
which peer you want to connect
to when you call the
invitation handler.
When that happens,
much like before,
the two session objects
will attempt
to establish a communication
link with each other
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and when they are done, you
will be notified via a delegate
method, peer:didChangeState:.
So that was programatic
discovery.
Let's now take a look at
how you can set up security.
So we provide two
things for you.
We provide support for
authentication and encryption.
So let's take a look at how
you can set up authentication.
To set up authentication,
you'll want to instantiate
your session object,
using a different init method
and that method will require you
to pass three parameters.
The first one will be the same
as before, a peer ID object.
And the second one will
be your security identity.
The third one will be encryption
preference, which we will handle
in more detail when
we cover encryption.
So for now, let's take a look at
the security identity parameter.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Well, identity is an NSArray
object that should adhere
to a specific structure, which
is depicted on this slide here.
The first object needs
to be your identity
and that identity needs to
be of type SecIdentityRef
and that first object
is followed by a chain
of certificates of
type SecCertificateRef
that validate your identity.
This is the same format
that Secure Transport
uses in their APIs.
Now at this point,
assuming that you've set
up your identity properly
and the peer that you want
to connect to also set up
their identity properly,
once the two session
objects establish a link
with each other, we will
exchange the two certificates
for you.
And once you receive the
certificate from the other peer,
your session delegate
will be called
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
with session:didReceive
Certificate:fromPeer:
and you will be passed
a certificate handler.
The second parameter will be
the certificate of the peer
that you're attempting
to connect to
and this certificate will
have the similar structure
as the one we've seen before,
just the first object will
not be a SecIdentityRef,
but it will just be
a peer certificate
of type SecCertificateRef.
The third parameter will tell
you the peer ID of -- of --
of the nearby peer that
the certificate belongs to.
And the fourth parameter
will be a certificate handler
that you will have to execute
once you've decided whether you
trust that certificate or not.
So again, it will be on you
to make that determination.
Once you get the certificate,
you will need to examine it
and make the decision
whether you trust it or not.
Once you make the decision,
you will notify the framework
by calling the certificate
handler
and passing it your response,
either a Yes or a No.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So that's how you set
up authentication.
Now, let's take a
look at encryption.
To set up encryption, you
will use the same initializer
that we mentioned when we
talked about authentication
and you will have to
use the third parameter,
encryption preference.
Now for encryption preference,
we provide you with
three options.
One is encryption
preference None.
If you decide to specify
encryption preference None,
that will mean that you do
not want to encrypt data.
If somebody wants to encrypt
data on the other side,
you will not be able to
connect to that peer.
The second parameter
will be Optional
and if you specify
Optional, that will mean
that you are willing to either
encrypt or not encrypt data.
You're fine with both options.
The last option is
encryption preference Required.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So if you specified
encryption preference Required,
that will mean that you will
be able to communicate only
with those peers who have
set that option to Required
as well, or to Optional.
If a nearby peer set
that preference to None,
you will not be able to
connect to that peer.
And that's really all you need
to do to set up encryption
and make sure that
nobody can eavesdrop
on your data in the session.
So to summarize the
advanced part,
we've covered programatic
discovery, we've mentioned
that you can use
MCNearby advertiser
and MCNearby browser classes
and using these classes will
enable you to handle events,
like found peer, lost
peer, and do stuff
like sending invitations
and responding
to invitations programatically.
That will enable you
to build custom UI
if you have the desire to do so.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And also, we've told you
how to set up security
in your sessions, specifically,
we told you how to set
up authentication
and encryption.
Now I would like to cover
some best practices for you.
So I would like to
encourage everyone
to start advertising
on app launch.
So once your app launches,
you should start
advertising your peers.
Why do you want to do that?
Well if you want the
user to press something
to make it self-discoverable,
then it will inevitably happen
that user just won't do that
and when somebody will
start browsing they won't --
won't see if somebody's nearby
because the other user forgot
to tap -- tap the Make
Me Discoverable button
or something.
So we encourage you to start
advertising on app launch.
Stop advertising
when not needed.
So once you've connected
into a session,
you might not be interested in
receiving invitations anymore.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
If that is the case, then
just stop advertising.
Stop browsing when done.
If you use the
framework-supplied UI
for browsing that we've
covered in the first stage,
you don't have to worry
about that, because as soon
as you dismiss the
browser view controller UI,
we will stop browsing for you.
On the other hand, if you choose
to do programatic browsing,
then you will actually have
to call stop browsing method
to do -- to stop browsing.
And you might want to do that
once you're in the session
and you're not interested in
any -- anymore who is around.
Also, we'd like to encourage
you to keep discovery info
and display names short.
That will optimize
networking performance.
And lastly, if you
are sending messages
and you want these messages
to arrive as soon as possible
to the recipient, so with
minimum possible latency,
we encourage you to
use unreliable mode
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and we encourage you to
keep these messages short.
Short here means on the
order of few 100 bytes.
So for more information, you
can talk to Paul Danbold,
our evangelist, and you
will find more documentation
about Multipeer Connectivity
in the Multipeer Connectivity
Framework Reference.
And, as always, you can meet us
at the Apple Developer Forums
and you can talk to
each other and us
if you have further questions.
And that's it.
Thank you very much for coming.
[ Applause ]