Transcript
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
>> Good afternoon.
I'm Noah [phonetic].
I'm here with my
colleague Nick [phonetic].
And we're here to talk to you
about what's new in
Passbook in iOS 7.
Now, some of you have been
building really awesome things
on top of Passbook already, and
we've had a bunch of requests
from you for enhancements,
for new features,
and we've addressed
a ton of those,
and we've added some
new stuff as well.
And I'll be going into all
of that in a lot of detail.
Some of you have looked
at Passbook before
and considered using it
but found it didn't quite fit
your use case at the time.
And we've made a couple of
changes that may affect that,
so I'll be calling
those out as well later.
And, finally, some of you
are entirely new to Passbook
and just kind of curious
about what's going on.
So I'll be -- while our
talks last year went
into a bunch more detail
about how to get started,
how to build your first
pass, and that kind of thing,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
I'll still be covering some
high level concepts just
so you have some
idea what's going on.
So without further
ado: let's get started.
There's three main topics
I'll be covering today.
First the Passbook
ecosystem: the different parts,
how they fit together, how
they all talk to each other.
Second: what's new,
what we've added
to passes, to our APIs, the app.
And finally a couple
of tips, tricks,
ideas that might help
you with your debugging
and your development of
Passbook integration.
So let's go to the first
of these, the ecosystem.
To start with: what is a pass?
Well, it's just information
like any other,
but what makes a pass more
useful than just a photo
of a ticket, for instance, is --
first, that it can be
relevant to a time and place.
And second, that it can be used
for something in the real world:
to get into something, to buy
something, to do something.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So how does a pass get
from you to your users?
Well, it starts with
your server,
which generates the pass.
Then it goes through your
website, or an email,
or an app of your own if
you have some existing flow
like buying a boarding pass.
From any of those three,
it goes into Passbook,
into the user's pass library,
and from there they
can interact with it.
There's a couple other
places that it can show
up on the system, and I'll
talk about those more in a bit.
But the core of it is that
it comes from these apps,
goes into your library,
and that's kind of that.
Now, a thing about passes:
since they represent
real-world information,
you expect them to
be up- to-date.
They should always
reflect the current state
of whatever they're
supposed to be used for.
And we could make you go through
that whole flow all over again,
direct your users back to
your app, send them an email,
back through your app, but
that would be a huge pain
and no one would do that.
So we have a better system,
and it's built on top
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
of the Apple Push
Notification Service.
Your server sends us a
push, we make a request
to your web service,
and you send us
down a new version
of the pass file.
And that seamlessly
replaces the existing pass
in the user's pass library,
and to them the pass is
magically now up-to-date.
So the user has your
pass, it's up-to-date,
how do they then use it?
Well, they bring their
device to your location.
You scan it, the barcode
on it, with some kind
of point of sale system.
That then talks to your server,
which checks whether the pass
is valid, whether it can be used
for whatever transaction
they're trying to complete,
and finds out, okay, the
pass is available to use.
It sends that information
back down,
you complete the
transaction and that's that.
Now, if something changes
about the pass as a result
of this transaction, like
if you've used a coupon
that can no longer be used,
or if you have a store card
whose balance you're updating,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
your server might
take that opportunity
to then send an update
notification to the pass
and get it up-to-date.
So that's just a vague
high level overview.
Passes are information
that can be used
for something in the real world.
They come from your server.
They get into the user's
pass library via your apps
or via Mail or Safari.
And they are then used by
scanning the barcode on the pass
and checking its
validity with your server.
And finally they can be
updated via the push system
to make sure the pass has the
most up-to-date information.
So that's the ecosystem.
Let's talk about what's
new in Passbook in iOS 7.
First, we've added ways for
you to enrich the content
of your passes, to
make them more useful,
work better, look better.
We've added easier ways to
get passes into Passbook,
both via APIs and via
some really cool new
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
user-facing features.
We've given you more
control over the relevance
of your passes, over when they
show up on the lock screen
of your user's device.
And, finally, we've
added better support
around the whole
using-passes thing.
I'll be more clear
about that later on.
So let's talk about the first
of these, the pass content.
A pass is kind of
structured like an app bundle:
it's a folder that's zipped up,
and the contents look like this.
You have your pass.json which
defines what the pass is,
how it behaves, how it looks.
You have a couple of
localized string files,
the lproge [phonetic]
folders that you see here
which contain strings that get
substituted into your pass.json
for user-facing strings.
You have a couple of icons
and images that we use
to display the pass in Passbook
and elsewhere in the OS.
All of that is signed and
zipped, and there's your pass.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So you may have noticed that
things look at little different
in iOS 7, and Passbook's
no exception to that.
Things have less gradients,
they have less shine,
subtler shadows,
that kind of thing.
And for the most part
that won't affect you.
We already will apply the
new look to your passes.
But if you've been
making a particular effort
to match the iOS6 style,
if you've been creating
your own gloss
or if you've been sizing
images to fit precisely
within the boundary of
the strip or anything,
then that's going
to look wrong now.
Your passes will look
slightly out of place.
It won't be the end
of the world,
but it will look slightly off.
So the rule of thumb for
that is, well, don't do that.
Follow our guidelines, supply
us the images in the style
and format that we expect,
and trust that we'll
do the right thing when
and if the appearance changes of
what we're applying to passes.
So there is one change to
the appearance that's going
to affect your images that you
will probably need to adapt for,
and that's that passes are now
the full width of the screen.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
They're 320 points, up from 312,
which means that your
strip images need
to change as well for that.
We'll currently take
your strip image
and scale it up a little bit.
But if you want it to be pixel
perfect, which of course you do,
then you want to change
those images for iOS 7.
And we also no longer expect
you to etch your logos.
You don't need to apply shadow.
Just give those a solid color,
and it will fit right
in, it will look great.
Finally, while iOS 7 Passbook
will only run on Retina devices
because those are the only
ones that support iOS 7 --
we aren't in iPad,
for instance --
you do still need to expect
that your passes are going
to show up on iOS 6 devices.
So you might have them
on the non-Retina screen
on the iPhone 3GS for instance.
So still provide
non-Retina images.
Even though a lot of your
users are going to be
on iOS 7 this fall, be
ready for your passes to end
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
up pretty much anywhere.
So let's talk about grouping,
which is a behavior we
haven't gone into a lot
of detail before, but
you've certainly noticed it
if you've been producing
multiple passes.
Passes group automatically.
Based on a couple of rules,
details not very important,
but sometimes the grouping
behavior is not exactly what
you expect.
If you have an itinerary,
for instance,
for a couple different people,
we might be grouping all those
passes together into one morass
which you might want to
have better control over.
So we now have this
grouping identifier key.
It's just a string.
You specify it and
any passes of yours
that have the same grouping
identifier will group together.
Any that have different
ones will group separately.
So you can use this on event
tickets and boarding passes,
which are the passes that are
most likely to be grouping
in these kind of
cases, and that's useful
if you're doing something
that involves an itinerary
or a multi-day event.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So, if you need that, use it.
That's what it's there for.
[ Applause ]
So let's talk about something
different entirely: date fields.
This is a feature that
we added in iOS 6,
basically to make
users' experience
around localization better.
What we do is you give
us an absolute timestamp
and a date style -- short,
medium, long, et cetera --
and we format the
time in a format
that the user will
expect to see.
So if they have their locale set
to show three o'clock or 15.00
or anything like that,
we'll show your time
in the format they
expect it to be,
and it will look
right, it will fit in.
So something that comes
out of our using this
timestamp format is
that we get automatic
time zone adjustment.
So if you have something
like a pass that specifies
that it occurs in in
12 p.m. Pacific time,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
then the user will
see that as --
I always get this stuff
wrong -- 3 p.m. Eastern.
So that's great.
It usually works in the way
that the users expect it to,
but sometimes you don't
want that behavior.
Sometimes you want to show a
time in the local time zone
that it's going to happen.
If you have a boarding
pass, for instance,
you want to show
the departure time
as when they get to the gate.
Or, if you have a hotel
check-in, for instance,
then again you want to show that
as the time that it is there.
Because people have trouble
converting between time zones,
like I just did, and you want
to help them out with that.
So what we now allow you to do
is to control how that works.
And the workaround that
some people have been using
for this is to just
use text fields
and say "3 PM" for instance.
And that works, your users
will probably get it,
but it's not the
best experience.
It could be better, and we
like making things better.
So we now allow you to disable
that time zone adjustment.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
It's just a key on date fields.
You say "ignore time
zone" and we drop that.
We show it always in the local
time zone that you specify.
The format hasn't changed:
you can't just leave it
out because we're still
validating against it.
But what you should probably do
here is specify the local time
zone that whatever time you're
trying to show is happening in.
So iOS 6 device users will
get the right experience,
more or less, and iOS 7
ones will get this nice new
ignoring-time-zone behavior.
So that's date fields.
Let's talk about the back of
your passes, about app links.
This is a feature that we
added for a couple of reasons.
It can help promote your apps,
and it provides easy access
to the apps if they have some
way of interacting with a pass
in the user's pass library.
So it looks like this.
You have this banner at the
top of the back of your pass,
kind of like the one in Safari.
It shows your app icon.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
It shows a button that
will either take them
to an App Store page which
will let them install it
if they don't have it already.
And if they do have it then it
will let them open the app right
from the back of your pass.
So if you have a store
card, for instance,
this can let them
easily get into the app
and check their rewards
or anything like that.
So the question that arises with
these app links, particularly
when you have an app that
can provide multiple passes
like an event app, for
instance, is, well,
which pass did the
user just come from?
You know that they
got into your app,
but you have no idea what pass
they want to interact with.
You might have them go through
your list of passes you have
in your library and
say, you know,
which pass are you
talking about?
But that's not ideal.
It's an additional step, and
they already chose this pass
when they flipped it
over to get to your app.
So what we now allow you to
do is provide a context URL
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
which we launch your
app with as soon
as the user taps the open
button on the app link.
And so that's really useful
to immediately get
you the information
as to what pass they
just came from.
You might even embed additional
information in the URL itself.
But thanks to this next feature
you don't actually even have
to do that.
Because what we now
have is pass metadata.
You can embed a dictionary
of arbitrary information
in your pass, and your
app can read it off
with a user info property
on a PKPass object.
So what this means is that you
can get semantic information
about the pass without having
to make a round trip
to your web server.
You don't have to check the
serial number with your server
and pull down additional
information,
wait for the network
latency and all that.
It's just right there.
So your app can quickly
and easily show information
about the pass to the user.
It can even do it in conditions
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
where there's no network access
-- on an iPod, for instance.
So that should be really
useful if you've got an app
that integrates with
your passes.
And one thing about this is that
while you can probably trust
that this information
did come from you,
because you signed the pass,
it might not necessarily
be up-to-date.
So if you have anything
valuable or sensitive,
like a store card
balance, for instance,
you should still check
it with your server
if you have the opportunity.
So that's app links.
Let's talk about text
links, and the text
on the back of your passes.
The idea for these is that
you can provide additional
information related
to your passes.
So you can provide
contact information
or the location of an event.
And to make that more
useful for your users,
we run data detectors on
them: we turn things that look
like useful information
into links.
So an address opens maps,
a phone number allows them
to call it, that kind of thing.
But sometimes that
doesn't behave right.
You can see here I have a
confirmation number that's being
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
confused as a phone number,
and an address that --
I don't know whether
this exists --
but it's not a real place
which we shouldn't be
giving directions to.
So what we now allow you
to do is control this
and set what kind
of data we detect.
So your confirmation
number stays clean of links.
Your things that you don't
want to be directions
to they don't turn
into directions links.
And that's going to
be really helpful.
And your users probably
weren't bothered by this,
but it was a little confusing.
And this makes your
passes look better.
So the way this works
is an array
of strings containing the
list of data detector types
that you want us to run.
So that can be phone
numbers, addresses,
emails, anything like that.
You just provide the list of
what you want us to detect,
and anything you leave
out we won't look for.
So the default, of
course, is "all".
If you don't provide this key,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
then we just do our
existing behavior.
But if you're seeing any issues
with data detectors turning
up when you don't want
them to, use this.
It will help.
I mentioned URLs,
and this is something
that we've heard a lot
about from you guys.
Specifically, that
when you embed URLs
on your passes, they look bad.
They're long, they're
ugly, they're opaque.
You can have a long URL
with your company's website,
or you can have a
URL-shortened one
which is not your company's
website but is even more opaque.
So that's not the ideal user
experience, and you have
to include lots of explanatory
text saying "if you want to talk
to our nice support people, tap
this link below," et cetera.
So what we've added to
fix this is embedded URLs.
[ Applause ]
So it works like this.
There's a new key on your field
that's called attributed value
which is in addition to
the existing value key.
So you can see here
I've included this
with more information,
explanatory text,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and I've also included
a much shorter --
at least to the user's eye --
version of this which does the
same thing and looks way better.
So it's a standard
HTML-style link tag.
You've probably seen it
before, but it's not full HTML.
If you want to make your
text bounce around the screen
or do marquees or sparkle, no,
no, we don't let you do that.
And it's only on back
fields, of course,
because as before we
only allow links there.
But that should be a great way
to make your passes look way
better and to simplify things.
And basically it means your
users have a way better
experience with your passes.
One note about this.
iOS 6 devices have no idea what
an attributed value key is.
You still need to
include the value
for backwards compatibility,
so: do that.
Let's review all this.
First, we have the new look.
If you've been matching the old
style by making your own gloss
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
or shadows or fitting
things to the dimensions
that you thought were
going to be forever...
don't do that.
Just follow our guidelines,
and we'll do the right
thing with your graphics.
We now allow you
to do date fields
without time zone adjustment.
We've added app links for
context URLs along with metadata
which allows you to pull
information off your pass
without having to make a
round trip to your server,
consume resources, et cetera.
And, finally, we've given
you better links on the back
of your passes via more
control over data detectors
and via the new embedded URLs.
So that's what's
new in pass content.
Let's talk about how you
get passes into Passbook.
We've made a lot
of changes here.
The first one -- well,
first, an overview.
Passes, as I said,
come from your server.
They go through Mail or
Safari, which can handle things
on their own, or in your apps
you have a couple of APIs,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
the PKAddPassesViewController
which allows you
to present a pass to be added
to a user's pass library,
and a couple of PKPassLibrary
methods that allow you to update
and remove passes
from the library.
And the thing about this is:
if you have a bunch of passes
to get to the user you have
to add them one at a time,
one after another, present
an add-pass view controller,
present another one, et cetera,
and your users are either going
to get fed up going through
those or they're not going
to get fed up but they're
going to send you nasty emails.
And we want to save
you from that.
So what we've added is a new way
to get multiple passes
into Passbook.
And to demo that
I'd like to bring
up Nick Circosta [phonetic].
[ Applause ]
>> Thanks, Noah.
So as Noah said we've got some
great new features to PassKit
in iOS 7 to allow you to
get passes easier than ever.
So what we have here is a
relatively simple application,
a collection-view-based
application
and let's just go ahead and
run it and see how it looks.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
[ Pause ]
Yay, we're all going
to a film festival.
So if we were, say, running
this application on iOS 6,
and a user wanted to add a
movie ticket for each one
of these films, they would most
likely tap each on in turn,
and then you'd present an
add-passes view controller
for each one and
ingest it into Passbook.
But we're going to do something
a little bit cooler now
in iOS 7.
So what we have here is
a method that's called
when we tap the add button.
And as with anything, when we're
working with the pass library,
the first thing we want
to do is, of course,
get a reference to
the pass library.
Same as always, we
do a PKPassLibrary
alloc-init [phonetic].
Now, next we're going to call
this new method we've added,
called -addPasses:with
CompletionHandler:.
Now, in this particular
instance, we're passing
in this array of selected films
which contains all the films
the user has selected in the UI.
And it's going to return it
to the completion handler one
of two PKPassLibrary
add statuses.
So let's take a look
at the first one.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
As with all these notifications,
you should always make sure
that you're performing any
operations on the main thread.
So the first status
you might receive is a
PKPassLibraryShouldReviewPasses.
Now this means that the
user has tapped "review".
Now, you're going to initialize
a PK add passes view controller
when this occurs, and what you
might notice is that instead
of just passing in one
pass like in iOS 6,
we can now pass it
an array of passes,
which in this case is
our selected films array.
You're going to obviously
want to set the delegates
so you can get the notification
callback when the user is going
to just dismiss it, and
then we're just going
to present it to our user.
Now, the second status is the
PKPassLibraryDidAddPasses.
Now this means that the
user tapped "add all"
and chose not to
review the passes.
Now, we're also going to
update our movie posters UI,
and I'll touch on that
method in a moment.
I do want to add, just as a
piece of information to you,
that in a future seed --
this is not in seed 1 --
we will be adding a
third status to determine
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
if the user cancelled
adding those passes.
So as we continue down
the code we also have the
"add-passes view controller
did finish" delegate method.
And in this particular
instance we're also going
to update our movie
posters when that occurs.
Now, I've got a movie posters,
relatively simple method here,
we're going to use the
pass library -containsPass:
method to check to see if those
passes were actually added
to Passbook.
And when that occurs we're just
going to set a simple property
in our model and then
read our collection view
and fit a nice fade
on the passes we have.
Let's go ahead and run that.
[ Pause ]
Cool. Now I really want
to see Epic, Iron Man,
and the new Star Trek movie.
Let's tap add.
Now, as we said, the user
is going to be presented
with this alert,
and they can choose
to either review or add all.
Add all just means
add it to Passbook.
Review will mean "let
me see those passes",
so we're going to tap "review".
And there we have our
three movie passes.
And when we do that we're
just going to tap "add all",
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
they look pretty good to me,
and nicely animate those out.
Wonderful.
[Applause] And with
that back to Noah.
[ Pause ]
>> Thanks, Nick.
So that's pretty cool.
Let's talk about a bit
of the details behind it.
It's a method on
PKPassLibrary as Nick said:
-addPasses:with
CompletionHandler:.
And you can call this and it
will just present that alert
where the user can
then easily just tap
"add all" or, as
you saw, "review".
If it's "add all" then
your passes just go
into their pass library.
There's nothing more
that you have to do.
If they tap "review",
though, you're responsible
for then presenting a
PKAddPassesViewController,
which has this new
initializer, -initWithPasses:.
So that will allow
them to then choose
to add all the passes
or cancel out.
And as you might
gather from that,
both these APIs are
all or nothing.
If the user doesn't want to have
one of the passes then they have
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to cancel the whole thing or
go back and delete it later,
which would be kind of a pain.
So what you should do, as
you just saw in this demo,
is provide your own UI for
choosing which passes they want.
If you have any situation where
the user is going to choose
from multiple passes, do that
first, then present this,
and you'll be good to go.
So that's the new API we
have around adding passes.
Let's talk about sharing.
You may have noticed, if
you've used Passbook in iOS 7,
that each pass now has a
share button in the corner.
And when you tap that
it brings up this sheet
which allows your users
to send passes via mail
or AirDrop or iMessage.
And this is really good
for some use cases,
and you may be possibly
worried about it for others,
but I'll talk about
that in a second.
What this means is that if you
have a pass that you want to be
in a bunch of peoples' hands,
that is now super easy.
They just say, you know, "hey,
friends, I went to Store,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
I got Thing, Thing is cool,
you should go to Store
and get Thing: take this pass".
It's great.
If you have a situation
where you've given one user
multiple passes that belong
to multiple people,
then they can then hand
out this movie ticket to
their friends they just bought
for this
everyone-going-to-see-a-movie
kind of scenario.
And, as I said, you might
now be worried about this
because your passes might now be
in multiple places and, "oh no,
where's my security model?"
That was already
very much possible.
Your users could
forward emails around,
they could share screen shots.
You might even have more
legitimate use cases
like restoring from an
iCloud backup or syncing
from one device to another.
So it's just now way more easy,
and we've made the
user experience
around it better,
as we sometimes do.
So the key thing to take away
from that is that if it matters
to you that your pass is on
multiple devices, validate them.
Check the barcode:
that's what it's for.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So that's sharing.
Let's talk about something
that you may recognize
from last year, the
Add to Passbook badge.
This has proved to
be really useful.
Users look for it,
they recognize it,
they know that it means "I can
tap this, I can get a pass,
it will be easy, it
will be awesome".
And it's great for
using in content,
in websites and email...
in body content.
But we've seen a couple of cases
of people thinking they have
to use it and wedging it
into their UI somewhere
where it doesn't fit --
sticking it in a navigation bar
or in an action sheet.
And you don't have to do that.
Just design for your app.
If you have some custom look
that this badge will not fit in,
don't use it: use
your own thing.
It will be all right.
So this badge ties
into a new feature
that we're really
excited about that some
of you may have seen
already, called code scanning.
And the idea here is it's a
really, really low-friction way
to get a pass into
your user's hands.
You don't have to send them
to a website, you don't have
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to get their email address,
you don't have to get them
to install an app:
it's just there.
And the idea is you put a URL
to a pass into a 2D barcode,
and from Passbook they
can scan that code
and turn it into a pass.
So we've had a bunch of ideas
about how you can use this.
I'm sure you'll come
up with many more.
But let's talk about
these a bit.
You've probably seen codes being
used in marketing materials
that say, hey, go
to our website,
scan this code instead
of typing it in.
But that's not the only option.
Your codes can be anywhere.
If you're printing something
individual like a receipt,
or a paper ticket
for some reason,
then you can put a code
that's unique to that user
on that receipt saying,
hey, here's a coupon
for Thing related to
Thing-You-Just-Bought.
Or, on an event ticket, you can
give someone a Passbook version
of their paper pass or
paper ticket rather.
But even if you are printing a
single code that's going to end
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
up in a lot of places, in a
magazine ad or on a banner
or anything like
that, they don't have
to point to a single pass.
You can just point that
URL at a web service
that can send down
a unique pass.
So you might be able
to get some information
on how many people
are using your passes.
Or, you could do something
like the first N people
who scan this code get
this really awesome pass,
that kind of thing.
So there's a bunch of
possibilities here.
And to show you one of the
ones that we've thought about
and implemented, I'm going
to bring up, again, Nick.
[ Applause ]
>> Thanks, Noah.
We're really excited about pass
scanning in iOS 7 so I'm going
to give you a quick demo here.
What we have here
is a simple web form
for a survey running
outside our movie theaters
on a nice little kiosk.
Nothing really advanced, just
some simple drop down fields,
and we'll make sure
those values are correct.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And we're going to
click all done.
Now, that's going to present
the user with a nice QR code
that they can scan with
their Passbook device.
But you may be asking, well,
what exactly happens here?
So let's take a look at
the URL that we're going
to be putting inside here.
So the URL is pointing to
a web server that's running
on this local laptop.
And you may be wondering,
well, why are there a bunch
of post variables on
the end of this URL.
Well, as Noah said, you
don't actually need to point
to a static PK pass file.
We can just point
to a generation service
and that [inaudible].
And you may be asking, well,
why don't we just, say,
send those variables away.
Well, the interesting
thing in this scenario is
that this kiosk doesn't actually
have to be live connected
to the internet in any way.
It can just be all locally
running and still be dynamic.
And the nice thing about
this is, of course,
prior to iOS 7 the user
would have to enter some sort
of email address for you to send
them a pass and now they don't.
One thing we do want
to point out is
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that if you are running
a generation service,
in this particular
case it's in PHP,
do remember the PKPass
MIME type in your header
so that Passbook knows that
you're giving us down a pass.
So, without further ado,
let's go and scan this one.
So we're going to
launch Passbook in iOS 7.
And, as Noah said, some
of you may have noticed
there's a scan code button.
So let's tap that.
In this particular
case we're going
to give our users a really nice
treat for filling out our form.
Who doesn't love free popcorn?
And that's pass scanning.
Thank you.
[ Applause ]
>> Thanks, Nick.
So we're pretty excited
about that.
We can't wait to see what
you people do with it.
Let's talk about a
couple of details here.
First the URL that you give
us has to return a pass.
If you point us to a website
and try to get your users fill
out an extra form or
whatever -- not going to work.
We will drop that on
the floor and say, hey,
sorry, this is not a pass.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So the URL has to be HTTPS
just like your web services.
We like things to be secure.
And this supports any
of the standard Passbook barcode
formats, QR, PDF-417, and Aztec.
Let's review all this.
First, we have the new
add-multiple-passes API
on PKPassLibrary and
PKAddPassesViewController.
And something I didn't mention:
the add-pass view controller,
you can still use
that by itself.
If you want to add
multiple passes
and you always want the user
to see them you can do that.
But if you're using
the PKPassLibrary API,
if the user chooses
to review the passes,
you have to use the add
pass view controller then
to show them the passes
that you're trying
to get into their library.
We have sharing which
is great for cases
where you want your pass to
be in multiple places at once.
But it also means that
since it's much easier
than it was before, you should
be validating your passes
if you care about them
being on multiple devices.
Just make sure that
you're doing that.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And, let's see.
So we have the Add
to Passbook badge
which we still encourage
you to use.
It works great in content.
If you're doing it in an app,
use it where it's appropriate.
Don't try to wedge it in places
where it doesn't look right.
And, finally, we have
the new code-scanning API
which is really cool and
is a super low friction way
to get passes into
users' pass libraries.
So that's what's new
in getting passes.
Let's talk about relevance
which I mentioned earlier.
The idea of your passes showing
up in your lock screen is
that it's really, really
easy to get to them.
It's a single swipe away.
Users don't have to open
their phone and unlock it,
dig through their
apps, find Passbook,
dig through their passes,
find your pass, et cetera.
It's just right there when
they need it, and that's great.
Users love that they
have this quick access.
And it's the most important
method that you can use
to get your users
to use your passes.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
If your pass is relevant
where they're ready to use it,
they will recognize
that and use your pass,
and you'll get that usage.
So there's something that we've
seen some confusion about,
both from users and developers,
which is the difference
between relevance
and notifications.
If you change something
about a pass,
that generates a notification:
you have something saying, hey,
there's something new here.
Relevance is passive,
so to speak.
It's a way to make
your passes available
when they're ready to be used.
So we just wanted
to clarify that.
In iOS 6, the API we
introduced was based
on geographic coordinates,
on points on the map.
You could specify ten locations
with geocoordinates and whatnot,
and within a certain range
of those places we'd make
the pass relevant based
on the pass style
and other factors.
And if you wanted to change
any of those locations,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
if you had a bunch of them,
more than ten, and your user was
in a particular area, or if you
had locations that moved around,
vehicles -- trains,
for instance --
then you would have to
push an update to the pass
to get those new
locations into it
which is not the
ideal way to do that.
So we have a new API for this.
It was meant to address
some of the requests we got
about this from developers.
It's called proximity.
It's based around iBeacons,
which you might have
seen mentioned
in the keynote on Monday.
The idea is this API on Core
Location which allows you
to have devices that
broadcast a unique identifier
over Bluetooth.
And the way that
we're using that --
since Core Location provides,
of course, APIs to pick
up that broadcast -- is that
we can now make passes relevant
whenever they're near
one of these devices.
And that allows you a
ton of extra flexibility.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
It means that you can have any
number of locations as long
as they have beacons
broadcasting the same
unique identifier.
If you have a location that
moves around, like a taco truck,
you can just keep a beacon
with you, and you don't have
to update the pass to say
"here is where I'm going to be"
because the pass
is already going
to be relevant wherever you are.
So that's really cool and
we're really excited about it.
Let's talk about the API.
It looks kind of like the
locations one, only instead
of a pair of coordinates
you're just specifying a
unique identifier.
And Passbook will look
for that identifier,
and when it is detected
your pass becomes relevant.
It's really simple,
it's really easy,
and it should help you a lot
with more flexible
conditions for pass relevance.
Of course we support up
to ten different beacons,
which is less important than
it was with the location API
because the beacons can all be
broadcasting the same unique ID
-- it doesn't really
matter how many there are --
but if you want to do
something different with those,
if you want to use,
for instance,
different relevant text
for different beacons
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
in a department store,
for instance,
then you can have multiple
beacons in your pass,
we'll look for those and
display the appropriate text
when we detect the beacon.
And, finally, something
really cool about this is
that iOS devices running iOS 7
can act as beacons themselves.
So if you have a
point-of-sale app or something
that is already integrating
with Passbook you now
have a really easy way
to make your passes relevant
when they're near
that point of sale.
You just have your app
broadcast the beacon ID
and we'll pick it up,
and your pass will be
on the user's lock screen and
you'll be ready to use it.
Pretty neat.
One final thing about relevance.
Something that we've had
some requests for is a way
to control how far away
a pass becomes relevant.
Because we use different
radiuses for these,
and if you have, for instance,
a bus station that's using
boarding-pass-style passes,
then you might see complaints
from a user saying, hey,
this pass is becoming
relevant like a kilometer
and a half away, what's
going on with that?
And the reason would
be, of course,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that we size boarding-pass
relevance for an airport or so.
So what we now allow you to do
is just control that distance.
You can specify a radius
around which your pass
will become relevant --
and note that that's a cap, not
a replacement for our value.
So if you want to make your pass
relevant all over the Bay Area,
then you're going to
have to put out a lot
of beacons or something.
So let's review all this.
First, relevance is a
quick, easy way for users
to get access to your passes.
Shows up on their lock screen.
They can swipe, get to the
pass, move on with their lives.
Relevance and notifications
are two different things.
One is active, one is passive.
Beacons now allow you to have
way more flexible relevance
by setting up these devices
and broadcasting a
unique identifier.
And, finally, we allow you
to control the distance
at which your pass
has become relevant
when using location API.
So that's relevance.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Let's talk about updates.
Now, this hasn't changed much
since iOS 6; we're just calling
out a couple things about it.
And first off, if
you're not using updates
when your pass can
change, you should be.
They're great.
It means that your pass can
be up-to-date, can stay alive
with whatever information
it's supposed to represent.
If you've got a
boarding-pass-type ticket
or a store card that doesn't
update when something changes
about it, then you're kind of
missing out on an opportunity
to make your user's
experience way better.
So a thing about updates is that
if you include a change message
for fields that have
changed then we show it
as a notification to the user.
And if you're going to use
that you should follow the same
principles that you would use
when sending notifications
via an app.
You don't want to
nag your users.
If you send a push
every couple of hours
to someone's store card
saying, "hey, there are things
in our store, hey, check out
this other thing in our store",
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
they're eventually going
to get fed up with that.
They're going to turn automatic
updates off and you'll lose
that channel to your users.
So use them sparingly.
Make sure there's
something the user cares
about when you're
updating your pass.
So I mentioned that
we've made some changes
around using passes.
As I mentioned, the idea is
that you scan the barcode
on the user's pass, check
it with your server,
and then complete
whatever transaction you're
going through.
And so the code scanning feature
that we showed off a
minute ago is actually based
on an API that's now
available to you in iOS 7.
And it's on AVFoundation.
It's part of the
camera metadata thing.
I'll refer to the talk
that talks about it
in way more detail later.
And so what this means is that
if you have a point-of-sale app
or something, like I mentioned
earlier, then you can now have
that kind of be an
end-to-end integration.
It can make the passes relevant,
and now it can scan the passes
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
for you, and you can
then do whatever you need
to do with them.
But this means you can
make better point-of-sales
and improve your user's
experience around their passes.
There are some third party APIs
people have been using already
for this, but we think
this one's kind of great.
And, of course, it supports
all the pass barcode types
like I mentioned earlier.
[ Applause ]
So let's talk about expiration.
Something we had a
lot of requests for --
again, both from users
and developers --
is a way to know when your
users can no longer use a pass.
So what we now allow you
to do is to mark a pass
as expired in the Passbook UI.
We gray out the barcode, we
show "this pass has expired"
in whatever language, and
that is basically just a way
that you can cue your users and
say, "hey, don't bother trying
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to use this pass: it's
been used already".
There's two keys that
you can use for this.
The first is an expiration date,
after which we'll automatically
mark the pass as expired.
And the second is a voided key
which you can push to the pass
if you want to immediately
update it --
if someone has just
used their ticket
or if their store card is
now entirely out of funds
or anything like that.
And you should note that
this is not an absolute.
You could be looking at a
screen shot of the pass,
the update might not
have made it to the pass,
so this should not be your form
of security just
graying out your barcode.
It's really just meant as
a visual cue to your users
to let them know when they
can and can't use a pass.
So as before, if
it matters to you
about your pass being used
multiple times or being
on multiple devices:
validate it.
Check the barcode
with the server.
That's what it's for.
So to review that, we have the
code-scanning API now available
on AVFoundation, and
we have these new keys
to expire your passes, to mark
them as expired in the UI.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And, again, if it matters
to you your pass being
on multiple places or used
multiple times: validate them.
Check the pass with your server.
So that's what's new.
Let's talk a couple of tips,
tricks, things to help you
with your development
and make your Passbook
integration better.
First, we have some
developer settings
which you may have seen before.
They're in Settings > Developer.
And they're really useful
for debugging your passes
and your web services
and all kinds of things.
First, there's a logging switch,
which allows you to see a bunch
of extra information
about what we're doing,
about what your pass
might be doing.
If you have validation
errors they'll show up there.
If you have weird
things happening
with your web service
like [inaudible].
We have a switch to
allow HTTP services.
If you're doing some
early development,
if you don't have your
server's certificate set up,
you can turn the switch
on, point your passes
at some local server
without any validation
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and it will just work.
And finally, we have a new
switch which ties into a feature
that we haven't really talked
about before but that some
of you may notice,
which is rate limiting.
So if you push a punch of
updates to a pass in a row,
that means we have to keep
downloading the pass over
and over again, and that
uses the user's battery,
it uses a bunch of
your server resources.
And so we will throttle
that back.
If we get a ton of updates
in a row we'll start
decreasing the rate
at which we actually
check for the pass.
And that helps users and means
if you have some
unexpected issues
in your push system
then you're not going
to get an unexpected spike of
server load, which is great.
But if you're testing something,
if you're actually trying
to send a ton of pushes
to a pass in a row,
then that's kind of
a problem for you.
And so you can turn this on
and we will update
the pass immediately
for every push that
you send to us.
So use that if you need it.
Something to note
about all of these is
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that they're only available
on development devices.
Your users will not have
these switches in most cases
and they will almost certainly
not have them turned on.
So your web services in
production do need to be HTTPS,
and they do need to be aware
at least of the rate limiting
that we do if you're
sending a ton of pushes.
So I mentioned that the logging
could help you find issues
with your web services.
And that will work great
for you if you're doing this
in a development
environment and testing
out the first implementation
of your server.
But in production we have
something else for you.
And this was mentioned
briefly in last year's talk
about the web service API.
And all it is is a way for
you to easily catch issues
with your implementation.
If your web service is
sending us down things
that aren't passes, or if you're
sending pushes that don't result
in an actual change to the
pass, we will tell you.
We will send a message to
this URL with logs on the end,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and that will let you know
that something is happening.
So watch this endpoint.
If you're getting reports
from your users of some issues
in production, you could make
a ton of surveys and ask people
"what were you doing when you
didn't get this pass updated".
Or, you can just watch
this endpoint and find
out what's going on
from us directly.
So that's really useful.
The most common issue
that we've seen --
and that we do message
to this endpoint --
is people not using the
Last-Modified/If-Modified-Since
system.
And the way that works -- again
more detail in last year's talk,
but I can summarize it --
is that when you update a
pass you can send out a header
with a blob of information
saying "here is
when we last changed this pass".
And then the next request we
make will include that header
and say "have you
changed it since then?"
If the answer is "no", your
server sends down an HTTP 304
"nothing changed" and we
don't download the pass.
And that saves both your users'
batteries and cellular usage,
and it saves your
server resources.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So: use that.
It's kind of nice.
So let's review all this.
First, the ecosystem.
Passes are information that
can be used in the real world.
They come from your server.
They get into the user's
pass library via apps
of various descriptions.
They're redeemed or used
by scanning the barcode
on the pass.
And you can update them
using our push mechanism.
What's new with passes?
We have richer pass content.
We have some easier ways
to get passes, both APIs
and user-facing features.
We have more control over pass
relevance, the new beacon API
and the new distance
restrictions.
And we finally have a couple
of things that could help you
around the whole
using-your-passes experience.
Tips and tricks: use
the developer settings.
They have real useful
information for you.
And use the logging endpoint
because it will help you catch
your errors in production
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
which is super useful.
Finally, we have a lot of new
APIs, as you've just seen.
We have a couple of
new user features
that can affect how you
integrate with Passbook.
If it matters to you about your
pass being on multiple devices:
validate them, check
the barcodes,
because it is way easier for
passes to be everywhere now.
And, finally, give us feedback.
You might have noticed that
I keep calling things out as
"this is from a request
we had from developers".
And there's a reason for
that, which is that a lot
of these ideas are based on
requests that we've gotten.
So tell us what you want.
We will listen.
We read every bug that you file.
You can talk to our evangelist,
Paul Marcos [phonetic].
There's documentation
on developer.apple.com,
and we will be in the
Apple developer forums.
Finally, there's a
couple of new sessions
that are related to this.
The What's New in Camera Capture
one is actually right now,
so you are too late, but you
can watch the video later.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
That talks about the new
AVFoundation code-scanning APIs.
The next talk, Integrating
Passbook Into Your Ecosystem,
is actually really
interesting because it's
from the Apple Store app team
who developed a really nice
integration of Passbook
with their gift cards that
was based entirely on the API
that you guys are using,
on the public APIs.
They aren't us, and you
can go to their talk
to get a really good idea for
what Passbook integration looks
like in a really large
scale, high value system.
So, go to that talk:
it is at 3:15.
Finally, the iBeacons API that
I mentioned is in CoreLocation.
Thanks for coming.
[ Applause ]
NW