Transcript
[ Music ]
[ Applause ]
>> Good morning.
Welcome to Advanced
Notifications.
I'm Michele, and today we will
be talking about a few things
about new notifications
in iOS X.
We'll start with the new
notifications user interface.
We'll go over a little
bit of an overview,
and we'll see what
changed in iOS X.
Then we'll see how to
use media attachments
in the new notifications,
and, last, we'll see how
to customize the user interface
for user notifications in iOS X.
to customize the user interface
for user notifications in iOS X.
Let's start with the overview
of the user interface.
User notifications in iOS X
have a beautiful new design.
You see here the new lock screen
with beautiful animations
and raise to wake.
Here is a banner.
You see they are
much more legible.
They have more content.
They show title, subtitle, and
this is notification center,
and notifications look the same
in all three [inaudible] places.
In iOS 8, we introduced
Actions Notifications
where you can add actions
to your notifications
to make them more interactive
and allow the user to deal
with that much more quickly.
In iOS 9, we introduced
Quick Reply
to enhance actionable
notifications
so you can even allow the
user to respond with text
that they type to
your notifications.
that they type to
your notifications.
In iOS X, notifications
are much more powerful
because notifications now are
more important to our device
as we interact with
them all the time.
They are a very important way
we interact with the device,
and a very important
way the user interacts
with your applications.
So in iOS X, you can
press on notification,
and notification will expand
and show a much more detail
specialized user interface
for your application, and it's
dedicated to your content.
It shows more detail, and
it's more useful to the user.
The user can also
tap on the actions,
and the user interface can
update and show what changed
and the effect of the
action that they just used.
Calendar, which just
a simple example.
We also have Find My
Friends, for example,
that when a friend shares
their location with you,
you see their location
immediately in notification
you see their location
immediately in notification
so you can see how late they're
going to be for your meeting.
We also have notifications
for Photo Sharing.
If you shared a photo on iCloud,
you can see the photo directly
in the notification
without opening the app,
and you can like it or comment
on it without opening the app
to look at the, at the picture.
At last, messages.
This is not all of it.
Messages support Quick
Reply starting in iOS 8,
but you could only
see one message,
and you can only
type one response.
Now you see the entire
conversation
when you open the notification,
and you can respond to it,
you can wait for your friends
to respond, and you type,
can type more responses.
This is the power of new
notifications in iOS X.
But is this was all there was to
it, I wouldn't need to stay here
for half an hour and show
you all the new notifications
in iOS X.
So the most important feature I
want talk to you about today is
that everything I just
showed you is implemented
that everything I just
showed you is implemented
with the new API's that we
are expand, exposing in iOS X
so you can do exactly the
same things that we've done
and add all the same features
to your own applications
and your notifications.
The first thing you can
do is media attachments.
You know, one of the most
frequent notifications I receive
by my friends are pictures
that they're sharing or videos.
So it's really important
that we have the content
that was shared [inaudible]
notifications
so I can see it more
quickly without having
to open the app and download it.
But the problem is
that, as you know,
push notifications are
delivered with push payload,
and even if we increase the
size last year to 4 kilobytes,
that's not nearly enough
to send an entire picture,
even if it's a small one that
we include in the notification.
So how do we do that?
We use the new service
extensions
that we introduced earlier today
in the previous presentation.
So to do, to download
the attachment
in the service extension, you
have to set your notification
to be mutable, as you
see here in the payload.
I send a mutable content flag,
and then you add a reference
to the attachment that you
want to send with notification.
In this case, I use
a simple URL,
but you could also
use a identifier
that your app knows how to
download from your own servers.
After you've done this, and
the notification is delivered
to the device, the system will
run your service extension.
In the service extension,
you can download the
attachment anyway you want.
Perhaps you can use
an URL session
so that the system helps
you manage resources.
And then the notification
is delivered
to the user with the attachment.
Let's see it, a little bit
of code on how to do this.
This is a very basic example
of my service extension.
At the top, I implemented
the didReceive request
withContentHandler,
and this is called
when the notification
is received,
and I have to download
my attachment.
I download my attachment, again,
for maybe using the URL session
or other techniques
that you prefer,
and when I have the
file downloaded locally,
I can create a notification
attachment object.
When I created the object, I
added notification content,
and I pass it onto the system
to be delivered to the user.
After I've done this,
this is my notification
with a beautiful picture
visible immediately to the user
without waiting for
it to download
or without having
to open the app.
And you see the notification
suite attachments support
actionable notifications to.
So you can like or comment this,
this picture directly from here.
So media attachments,
a quick recap.
They support local, every
[inaudible] notifications.
We only talked about local here.
We only talked about remote
because local ones are easier.
You just create the
notification attachment object
when you're scheduling the
notification, and you're done.
Attachments support
images, audio, and video,
and the system will
provide, customize UI
for this three types of content.
You download the attachment
in the service extension,
but you have to remember
that the service extensions
has limited amount of time
that it can run, and file
sizes are also limited
because these are meant to be
sent with the notification.
because these are meant to be
sent with the notification.
They're not meant to deliver
the entire content to the user.
So you may want to send
a scaled-down version
of the image, and then
download the full resolution one
when the user opens the app.
Or you may want to
send a short video clip
if you're sending a video, and
then download the full video
when they open the app.
When you downloaded it, you
add it to the notification,
and at this point,
the system takes over
and manages the file for you.
You don't need to worry
about the file anymore.
The system moves it
to a separate location
and handles all the data.
Oh, yeah, I almost forgot.
Of course, we support GIFs.
[ Applause ]
So attachments are pretty cool,
and they provide a very rich
interface for notifications,
and they provide a very rich
interface for notifications,
but at the beginning I said that
you could implement everything
that I showed you with the new
notifications, and calendar,
messages, and they
were definitely not
using attachments.
They were using custom
user interface,
and this is what we're
talking about now.
To create a custom
user interface,
you use the second
extension point that we added
to our standard notifications,
and it's a
NotificationContentExtension.
The NotificationContentExtension
allows you
to add your own views,
custom views.
You can draw anything
you want, but the main,
most important limitation is
that there is no
interaction with your views.
They don't receive touches.
The user cannot tap on them.
But notifications
are still interactive
because you can use
notification actions,
and the extension can
handle those actions,
and we'll see later
how to do it.
So I said that we can
implement the same things
that the system is doing.
Let's start by seeing
what calendar is doing,
and then we'll see how
to do the same thing.
This is a calendar notification.
You see at the very
top there's a header
with the notification icon that
you can tap to open the app,
the application name,
and the dismiss button.
This is standard UI
that the system provides
to all notifications.
Underneath the header,
there's the custom content,
and this is where your
notification extension
will live.
This is where you
draw your content.
You show all the extra details
that you want to the user.
And underneath these,
there's a default content
that the system shows.
This shows the content that
was delivered with the payload.
This was what was visible until
iOS 9 in the notification.
And at the very bottom, there
are actions that a user can tap
And at the very bottom, there
are actions that a user can tap
and interact in notification.
When the user taps on them,
the user interface can update
and show what happened.
So let's see how to make
one of these ourselves.
We'll start with a party invite.
Parties are fun, and we're
going Thursday, right.
This is the basic notification
that will be displayed
by the user when you just
send a push notification,
and it's pretty similar
to what you expect.
Let's see how to expand this
and show custom user
interface like we wanted.
The first thing you want to
do is to create a new target
in your application, and you
do that by using the template
that Xcode provides,
the NotificationContentExtension
template.
This template will create
three files in a new target.
A view controller, main
interface storyboard,
and the info.plist
where you can set
up customizables
for the extension.
This is the view controller
for the
NotificationContentExtension.
As you see, it's just a UI
view controller subclass.
It's a regular view controller
that you use as you're used to.
It also implements the
NotificationContentExtension
protocol, and this is what
tells the system that you want
to use these view controller
for the notifications.
This protocol has only
one required method.
The required method is
didRreceive notification,
as you see here, and this
method is called together
with the view controller
life cycle method calls
when the notification is
delivered to your notification.
To your extension.
So when the user
expands the notification,
you will receive all the
view controller calls
and these one in addition.
So you can receive the
notification object
So you can receive the
notification object
and update your UI and
show different things.
The, the next thing you want
to do is tell the system how
to find your content extension.
Content extensions, you use the
same notification categories
that you use to register
notifications actions.
In this case, I use
the event invite
for my party invite invitation,
but extensions can
also be associated
with multiple categories in
case you want to use the same UI
for different types
of notifications
that may be similar.
In this case, I'm using the
event-invite or event-update.
They could be very similar UI's.
So I can just use the
same, different categories
because they may have
different actions.
So I set up everything.
I have my view controller.
Now I want to add some custom
views to it to draw my own UI.
It's a very controller.
I added some labels
in my storyboard
that I'm not showing
here, and I'm,
that I'm not showing
here, and I'm,
when I receive the notification,
I'm extracting the content
to have the information I need,
and I'm setting the content
on the labels that
I just created.
You see that I also have some
custom information additional
to the standard one that comes
with the payload because I want
to show something more than the
standard payload for displays.
In this case, I'm
showing the location
because it's pretty important
to know where the party is.
And this is my notification now.
You see that I have
some custom content.
I draw my own UI with my custom
labels, different styles,
but these notifications
has two problems.
The first problem is that
this content is too big.
I don't need all
that extra space.
It's all empty.
I have much smaller
content to display.
The second problem is that the
default content is duplicated.
The second problem is that the
default content is duplicated.
I don't need it because I'm
already displaying the same
information up top
with my custom style.
But we can fix both
of these problems.
Well, let's fix the
first, the second one first
because it's easier, and this
is an additional attribute
in your info.plist, and you can
just set default content hidden
to yes to hide the
default content.
The system will not
add that anymore.
The second problem was the
size of my notification,
but since it's just
the view controller,
I can resize it the way I'm used
to resizing view controllers.
In this case, I'm setting
the preferred content size,
but you can set the
constraints without the layout.
You can use the storyboard,
and they will both work.
And after fixing
these two issues,
this is my notification now.
It looks much better.
It's the right size
that I wanted.
There's no duplicate content,
but did you see there
was another problem now.
When the notification
was presented,
it was not the right size.
So the system had to animate
a resize the notification
to show it the right size.
Let me show it to you again.
See? We could make it better.
The reason this happens
is that the system needs
to know the size of your final
notification when it starts
to display it so you can
do the right animation.
But your extension
is not yet running
when the system starts
presenting the notification.
So you need to tell the
system in advance before any
of your code runs what size
you want to be at the end.
But the problem is that
these notifications run
in different devices
with different sizes
in different context.
So the way we do that is
that we set a content ratio,
content size ratio.
So these, this defines the
ratio of the height and width
that you want to use
for your content.
Now this may, of course,
not always be possible
because you may have
content of different sizes.
You don't know what
content you're receiving.
You still want to
display all of it.
So sometimes this may not
be possible, but if you can,
figure out a size that works
for your notifications.
This is the way to do it.
And the result after I've done
this is this new notification
that now present it directly
at the right size
from the beginning.
So let's review what
we have done so far.
We wanted to do a
custom notification UI.
We may, we started
with these custom UI.
That's pretty basic, but has all
my custom content has additional
information that was
not in the payload,
but it was the wrong size.
So we fixed the presentation
size
by using the initial
content size ratio.
And then we fixed the
duplicated content
And then we fixed the
duplicated content
by setting the default
content type hidden flag,
and we went from the
beginning to this.
This looks better
than when we started.
Still not great, but I
do have an appointment
that is unlocked
today to fix it.
But I also know another trick to
make notifications look nicer.
We can add pictures.
Pictures are always nice,
especially on party invitations.
So we can use the
same media attachments
that we used earlier also in
NotificationContentExtensions.
Since they're added to
the notification content,
you can access them inside
your content extension.
So when you receive the
notification [inaudible]
notification method, you
can extract the attachments
from your content.
As I mentioned earlier,
the attachment is managed
As I mentioned earlier,
the attachment is managed
by the system, and it's
moved to a separate location.
This means that it's
outside of your sandbox.
So you need to tell the system
that you want to start using it
and tell the system
when you're done.
When you have access, you
just use it as a file.
In this case, I'm adding
it to my image view.
And here's my notification now.
You can tell this
guy's ready to party.
[ Applause ]
This is much nicer than
the one we started with,
and it's our own custom UI.
We want, we wanted to show
additional information
to the user, and we added that.
We wanted to add a picture.
We have that, too.
Well, we missed the next step.
We want to make this
interactive.
We want to implement
the actions.
Let's do that now.
Default actions by
default work the same way
as you're used to since iOS 8.
They are delivered to the app.
When the user taps
on the button,
the app receives the
[inaudible] request,
and the notification gets
dismissed immediately.
This is pretty convenient
because it's a behavior
that you often use, and it's
pretty simple to implement,
but sometimes you want to
show the user the effect
of the action for,
like, in the example
of the calendar invitation.
That when the user
tapped accept,
the content highlighted the
event that I just accepted.
And you can do that in your
NotificationContentExtensions.
You do that by intercepting
the action
in the notification extension.
When you do that, the action
is delivered to the extension
and it can decide to delay the
dismissal of the notification.
So it has time to handle
the action, update the UI,
and dismiss when it's done.
This is very simple,
and you do it
with the second method inside
the NotificationContentExtension
protocol.
This method is optional.
You don't need to implement
it if you don't need
to intercept the actions,
but if you do implement it,
it means that you have
to handle all the actions
that are in that notification.
You cannot handle one and
not look at the other ones.
So when you receive
the notification,
you can send a response
of your server
to update the information
on the server.
When you receive the
response from the server,
you update the UI saying
that the user is going
to the party, of course.
And when it's done, you can
dismiss the notification.
So that the interface was
updated before dismissing it.
In case you want to
still forward the action
to your application,
you can do that, too.
If you want to do
additional handling,
or you want to keep the code
in, all in the same place,
or you want to keep the code
in, all in the same place,
you just call completionHandler
with a different parameter.
And what happens when we do this
is that we receive notification,
we tap on that, and
we can update the UI,
and we dismiss later.
So you saw in my example code
that we implemented the accept
and decline action, and we
have a third one at the bottom.
Because sometimes
when you're responding
to a party invitation,
you want to see,
we want to tell your friends
how excited you are to go
to the party or how upset
you are that you can't go.
So you tap on the
comment action.
The comment action is
a texting production,
like the ones we introduced
in iOS 9, and you use it
in the same way, except with
the new, awesome new framework.
This is a texting production.
A tiny bit of newer PI on this.
You can set the place
holder in the text field,
You can set the place
holder in the text field,
and when you created the action,
you can add it to your category
so that it's displayed
with notifications.
So when the user taps
on the comment button,
the text will display.
Now since this is an
action like the others ones,
you can handle it
in the same way.
So you can intercept it
inside your extension
and handle it there.
Here's how you do that.
You receive the notification.
You check if it's a
text input action.
You extract the text of the user
typed and send it to the server.
And when you're done, you
dismiss the notification.
And this is what happens.
You tap, type, and there's
a problem again here
You tap, type, and there's
a problem again here
with this notification.
I want to respond to the invite,
but there's only a send button,
and I can't say if I want
to accept or decline.
So what we would like to do
is to have the text field
but also two buttons
so I can accept
or decline the invitation.
Something like this.
Would that work?
Well, there's no new API to do
this, and there's no new API
because it already exists.
You can use the existing UIKit
custom input accessory view API
to add your own custom into the
text field to the notification.
[ Applause ]
To do that, the first thing
you want to do is to say
that your controller can
become first responder.
This tells both the UIKit
system that it's part
of the responder chain and
the notification system tells
of the responder chain and
the notification system tells
that you don't want the
standard text field.
Then you create your own
custom inputAccessoryView,
in this case, like mine,
there was a text
field and two buttons.
And then when I receive
the response, the action,
the comment action
from the user,
I can make it first responder
so that the text field
and the keyboard appears.
I need to do both calls here
because the first one makes a
view controller first responder.
So the text field appears,
and the second one makes the
text field first responder
so that the keyboard appears.
You notice that in this case, I
don't really, I'm not interested
in the fact that it's a
textable action or not.
You can use regular
actions because I'm going
to get the text from the user
from my own inputAccessoryView.
So I have access to that UI.
And the result of this is
that when you tap on comment,
And the result of this is
that when you tap on comment,
now you can type your response
and actually respond
to the invitation.
So this was all for
NotificationContentExtensions.
There are some other small bits
of the PI that you can come
and talk to us at the labs
a little later in the week.
And what we learned today is how
to use attachments in custom UI,
in Notification Content
Extensions in iOS X.
We learned how to download and
add attachments to notifications
by using a service extension.
We learned how to do
custom UI, fully custom UI
with your specialized content
with the content extensions
that can use media attachments
and can handle user interaction.
For more information
about all of this,
there's a special
page for this session.
there's a special
page for this session.
We had a session earlier today
that if you missed you can catch
up to learn about the new
user notifications framework
and more details about
the service extension.
Thank you.