What's New in iOS Notifications

Session 713 WWDC 2014

Local and push notifications let background or inactive apps notify users that an event of interest has occurred, or that an app has new information for them. See how to configure interactive notifications to let users act on notifications from banners, alerts, in notification center and on the lock screen. Learn how to trigger notifications using geofences and iBeacons, and discover the new API's for registering for user notifications and remote pushes.

[ Applause ]

Good afternoon, everybody.

So, my name is Dan Kurtz.

Today, my colleague, Rhett Dickson, and I will be talking to you about What's New in iOS Notifications and iOS 8.

So, before we get into all the great new features of iOS 8, let's lay down some foundation about what notifications are and how you have been using them in iOS 7 today.

So, when I mention notifications, I'm actually talking about two different types of notifications, really.

We've got user notifications and we've got silent notifications.

So let's start off with user notifications.

What are these?

So, user notifications are really just things that the user can interact with, see or hear on their device.

And they're coming directly from your app.

So, for instance, with the messages icon up here on the top left-hand corner of the screen, let's say that the user happened to receive a message from one of their friends when the app is currently not in the foreground.

Well, we've got three different options for user notifications that we could use to let them know that there's new information.

First one that we could do is badge the app icon.

Having that little red circle with the number 1 in there informs the user that they've got one new message.

Now, for times that the user happens to have that device in their pocket and they might not be able to see the screen, we could instead play a sound [sound plays] informing the user that they've got a new message.

And lastly, we have alerts, which tick down as that banner from the top of the screen with a little preview message of what that message actually contains so that the user doesn't even have to tap on the messages icon to check out what's there.

So we have badges, we have sounds, we have alerts.

And for alerts, they can actually appear in different forms and in different places as well.

Depending on how the user happened to set their settings for your app in the notification center settings, these alerts-instead of being those banners that tick down and then go away automatically-they could appear as modal alerts.

They'll stay up there on the screen until the user happens to interact with them.

And then we also have alerts that they can be displayed in the notification center drag down as well as for the time that the user happened to have the device in their pocket and the screen was off when they happened to receive an alert.

Next time they turn it on, it's waiting right there for them in the lock screen.

So, where do these notifications come from?

Well, for user notifications they can come from two different places.

First off, they can be coming directly from your app.

That is, your app uses UILocalNotification API to present a notification to the user.

Alternatively, you could also have user notifications that are triggered in response to remote push payloads.

You've got an APNs server, the app out there on the Internet.

In coordination with the Apple Push Services, you send a push payload that defines, in this case, an alert in it-oh, sorry,-that results in an alert that will appear up on the screen.

Now, I go a little bit over eager there.

We've also got another type of notification.

I mentioned we have user notifications and silent notifications.

Silent notifications, they are just push payloads that are sent from your APNs server that, instead of presenting a user notification like an alert or a sound or a badge on the screen, iOS, when it receives that push, will instead wake up your app in the background so that your app can do some background image processing or information processing.

In this case, your app is fetching content from a server so that the next time the user happens to tap on your app icon and bring it to the foreground, that information is there and ready so nobody has to wait for a loading spinner to complete and all that other stuff.

So that's notifications in iOS 7.

We've got user types, we've got silent types.

User notifications can come from locally on the app.

Remote notifications, they can only be coming from push payloads.

So let's talk about the new features of iOS 8 notifications.

We're going to be talking about four great new topics today.

First, I'm going to be talking about user notifications, what's changed about them in iOS 8, specifically with registration.

Then Rhett is going to come up and he's going to talk about a great new feature, notification actions.

These are those interactive notifications to make your app interactive even without it being there, foreground on the screen.

Then we're going to pass the baton again.

I'm going to come back to talk about remote notifications, some changes that we have there for registering.

And then finally, we're going to talk about one last new feature, location-based notifications.

User notifications that are triggered in response to the user changing their location.

So let's get on to the very first topic, user notifications.

So, in iOS 8, regardless of whether your app is going to display remote user notifications or local user notifications, your app must first register to use those notifications.

And this is going to result in an alert that is going to be presented to the user, asking them if it's OK for your app to present notifications to them.

So, what does this code look like?

How do we register your app in order to take advantage of user notifications?

Well, the code is actually pretty straightforward.

The very first thing you need to do is declare the types of user notifications that you wish to present from within your app.

In this case, this app is actually going to present all the different types of notifications it possibly can.

It's going to be showing badges on the icon.

It'll also be playing sounds as well as displaying alerts.

Now, once we've decided the types that we're actually going to be presenting, we're going to create a UIUserNotificationSettings object passing these types to settingsForTypes categories.

Now, that second parameter, the categories parameter, you'll notice that it's nil here.

Don't worry about it.

That has something to do with notification actions.

Rhett's going to talk about those later.

Finally, once we've created the settings object, we're just going to pass it to the shared application instance in registerUser NotificationSettings.

And at that point, assuming this is the very first time your app has called this method, the user is going to be displayed an alert asking them if it's OK for your app to present user notifications to them.

Now, they're either going to say OK or maybe not now.

But no matter what they do, they could always, at a later time, background your app and change their preferences and settings.

So this isn't the last time that you have a chance in order to present notifications to the user.

So, once they've actually replied to that alert, your app delegate is going to get a callback, application didregisterUser NotificationSettings.

That notification settings object that we pass back to you represents the user's up-to-date, most current preferences for displaying notifications.

And at that point, all you need to do is check what types of notifications you're allowed to present to the user.

So, again, like I mentioned before, there is the possibility that the user could always background your app, go into settings and change their preferences.

And you need to stay on top of this.

You don't want to be doing any unnecessary processing for, say, preparing a alert-type notification when you don't really need to.

So, we have API in UI application as well.

This currentUserNotificationSettings method that is available in the UI application instance will give you the most up-to-date user notification preferences.

And from there you can make sure that you're not doing any unnecessary work to prepare for notifications that aren't going to be displayed to the user anyway.

So, that's user notifications.

Really, it's just a registration method to state that your app wishes to use user notifications.

And to do this, you just need to call registerUser NotificationSettings on the UIApplication shared instance.

Any time you need to get the most current user preferences, you just have to call currentNotificationSettings on UIApplication.

And in order to create these settings objects at the time of registering, you just call settingsForTypes: categories.

And recall, I said the categories was nil in the previous sample slide.

And that has something to do with notification actions.

So, Rhett's going to come up on stage and talk about notification actions, a great new feature in iOS 8 that I can't wait to see you guys take advantage of.

Thanks.

[ Applause ]

Thanks, Dan.

So, my name is Rhett Dickson.

And I'm going to talk about notification actions, a great new feature in iOS 8 that we're really excited about.

First, let's talk about notification actions in iOS 7.

Whether on the lock screen, notification center, banners or modal alerts, you get one default action when you swipe or tap on the notification that launches the application in the foreground.

In iOS 8, in addition to that default action, when you swipe to the left on the lock screen, you get two new actions.

Likewise, in notification center, when you swipe to the left, two new actions.

In banners, when you pull down, two more actions.

And in modal alerts, when you tap on the Options button, you get up to four more actions.

So, to use notification actions in your application, you need to follow three steps.

You need to, first, register your actions.

You need to, second, send a push or schedule a local notification.

And finally, once the user has seen these actions and tapped on one, you need to handle the action.

To illustrate these steps, I'm going to use the calendar invite example with three actions: Accept, Maybe and Decline.

So let's first look at registering actions.

You start off by creating your action.

You then set the identifier on your action.

The same identifier will be passed back to you when you handle the action.

You then set a title.

This is a localized string that'll be shown to the user.

You then set the activation mode.

This will determine if your application is launched in the foreground or the background.

If you need to show UI, you should choose foreground.

If you don't need to interrupt the user, you should instead choose background.

If you do run in the background, you'll have on the order of seconds, not minutes, to run.

You then set whether the action is destructive.

If this is Yes, the action will be shown as red on the lock screen and in notification center.

Finally, you set whether authentication is required.

If this is Yes, and the device is locked, the user will have to enter in their passcode when they tap on the action.

If your action is a background action, it's important to note that the device does not actually unlock.

So, if your application accesses any files on disk, you need to be sure that they belong in the correct data protection class.

For more information on data protection, we'll point you toward some more resources at the end of this session.

So here's an example of the accept invite action.

It doesn't need to show any UI, so it can run in the background.

It's not destructive, so it's shown in blue in notification center and on the lock screen.

And because accepting an invite is relatively harmless, you don't need to require authentication.

On the other hand, if you had a Trash Mail action, it also doesn't need to show UI, so it can run in the background.

It is destructive, so it will be shown in red on the lock screen and notification center.

And because you don't want someone to be able to pick up your phone and delete all your email, authentication is required.

Finally, we have a Reply action.

This does need to show UI, so it will need to run in the foreground.

Again, it's not destructive, so it'll be shown as blue.

And because it's a foreground action, if the device is locked, the user will have to enter in their passcode.

So, in this case, the authentication required property has no effect.

So, now that you've defined your actions, you need to group them into a category.

A category is simply a type of notification with associated actions.

For example, you can have the invite category, with Accept, Maybe and Decline actions.

You could also have a New Mail category with Mark as Read and Trash, or a tagged category of Like, Comment and Untag.

To start using the categories, you first create one.

You then set the identifier.

You'll include this identifier in your push payload and your local notification.

You then set the actions on the category for an action context.

There are two action contexts.

The first, the default action context supports up to four actions.

The second, the minimal action context, is used when there's only room for two actions.

So, for example, if you set these three actions, Accept, Maybe and Decline, for the default action context, and if this notification was then presented on the lock screen, you would see the first two actions, Accept and Maybe.

If you wanted a different set of actions, such as Accept and Decline, you could set those on the minimal action context.

Then when this notification is presented on the lock screen, you would see Accept and Decline.

When this same notification is presented as a modal alert, because this is the default action context, you would see the full three actions, Accept, Maybe and Decline.

So, once you've defined your categories, you now need to register them.

You do this by first grouping them together in a set, providing them to your user notification settings-this is where Dan left us off-and then registering those settings with your shared application instance.

So now we've registered our actions.

The next thing to do is to send a push notification or schedule a local notification to show those actions.

In the remote notification case, you need to include the category identifier in your push payload.

We'll use this to determine what actions to show when we present your notification.

We're also very excited to announce that the previous size limit of 256 bytes for a push payload has now been increased to 2 kilobytes.

[ Applause ]

So, in the local notification case, you create your notification as normal.

You then set the category of the actions you'd like shown.

Finally, you schedule the notification as normal.

So, once you've sent a push notification or scheduled a local notification and the user has seen this and tapped on an action, you then need to handle that action.

To handle the default action when a user just swipes or taps on the notification, launch your application in the foreground and call application: didFinishLaunching WithOptions, where we'll pass in the local notification or the remote notification.

In the remote notification case, we'll also call application: didReceiveRemote Notification: fetchCompletionHandler.

If your application is already in the foreground, we won't actually show the notification.

Instead, we'll either call application: didReceiveLocal Notification or application: didReceiveRemote Notification with fetchCompletionHandler if you've implemented that.

Otherwise, we'll call the version without the completion handler.

Finally, to handle the new additional actions in iOS 8, you need to implement at least one of two new methods on your application delegate.

In either case, we'll pass you the action identifier.

You can use this to determine what action was tapped on.

We'll also pass you either the remote notification or the local notification.

And you can use this to retrieve any information you need to handle that action.

Finally, we'll pass you the completion handler, which you must call when you finish handling the action.

So, to summarize, to use notification actions in your application, you first need to register your actions.

This involves defining your actions, grouping them into a category and then registering those categories with your user notification settings.

You then need to send a push notification or schedule a local notification, including the category identifier of the actions you'd like shown.

You then need to handle the action once the user has tapped on it by implementing one of the new methods on your application delegate.

Notification actions are a great new feature and we can't wait to see what you're going to do with them.

I'm now going to pass it back to Dan to talk about remote notifications.

[ Applause ]

Hey. So, let's talk about what's new with remote notifications in iOS 8.

So, recall we've got two different types of remote notifications.

We have user type remote notifications.

That's when your APNs server sends a push notification to the device wherein the payload we've got, in this case, an alert, that results in a user notification being presented to the user as if it was coming from the app that's running or installed right there on the device.

We've also got silent types of remote notifications.

This is when your APNs server is sending a push notification with a content available flag contained in it.

And then instead of us presenting a user notification on the device, instead iOS 8 is going to come in, wake your app up in the background, then it can go and fetch whatever content it needs to or do whatever info processing is necessary so that when the user next launches the app, all that info is right there ready for them to ingest.

So, for user notifications that are sourced from remote payloads, just like for local notifications, you must make sure that your app calls registerUserNotification Settings before any alerts or badges or sounds are actually going to be presented.

You will need to also register for remote pushes.

And we'll show how to get into that later.

Now, for silent notifications, just like in iOS 7 and before, you need to define in your info.plist file a UIBackgroundModes array.

And that array must contain an entry of remote notification in it.

So, user notifications, silent notifications, these are not mutually exclusive.

Your app actually can use both.

Mix and match them to whatever makes most sense for your users and for your app.

So, for remote notifications, you must make sure that you are registering before you can receive any pushes from your APNs server.

Now, in iOS 7, when you would register for remote notifications, we would ask the user for permission.

But now, since we have separated the concept of registering for user notifications, which does require permission, from remote notifications that could be user type or silent type, we actually are opting your apps into being able to receive remote notifications of any payload type by default.

However, keep in mind-ah, OK, cool.

[ Applause ]

Thanks! Keep in mind, however, that the user could at any time go into the settings app and change their preferences.

So, how do we actually register for remote notifications?

In iOS 7 and before, we asked you to call this method here registerForRemote NotificationTypes.

That's now deprecated.

Because we've change the way we define user notifications and remote notifications, all you need to do is call on UIApplication, register for remote notifications.

Now again, this will allow your app to receive remote payloads that are coming from your APNs server.

But if you want user notifications to be presented in response to those payloads, if you've got, say, an alert defined in those payloads, you also must make sure that you call registerUserNotification Settings, as I explained earlier in the talk.

So, once you've called registerForRemoteNotifications as well as optionally registerUserNotification Settings, your app delegate needs to implement applicationDidRegisterForRemote NotificationsWithDeviceToken.

This actually isn't new API.

This is something that has existed in iOS 7 and previously.

Just letting you know that you still need to implement this for handling remote notifications.

And what this callback does is it provides your app with a device token, where once you receive that token you need to go and pass it off to your APNs server.

Now recall, you need to make sure that you've always got the most up-to-date device token registered with your APNs server.

Otherwise, pushes may not make their way to the user's device.

So, in the case that the user happened to disable your app from using remote notifications, or for any other failure case, recall that the app delegate also needs to implement applicationDidFailToRegister ForvRemote NotificationsWithError.

And at this point, all you need to do is take that error object, process it appropriately and make sure you disable any logic within your application that's hinged off of receiving remote notifications.

You don't want to be doing any unnecessary processing within your app for notifications that aren't going to be coming in.

Just gracefully degrade.

So, that's what's new with remote notifications in iOS 8.

Again, just like before, you do have to register for remote notifications before you can actually receive them.

However, now in iOS 8, the user will be opted into receiving remote notifications.

And they could go into settings later and disable this.

However, it does still require you to call this registration API.

As well as this API has changed.

We've simplified it, and have named it registerForRemoteNotifications.

You can call that on the UIApplication shared instance.

Cool. So, let's get into the last topic of today, location-based notifications, something we're very excited about.

We've been working with the Core Location Team for this feature.

Very happy to talk about it today.

So, let's say that you've got an app.

And you want to notify the user when they happen to arrive at some certain geographic location.

So, the user is on their device and they happen to wander into that area.

And you want to show, say, an alert.

Well you could do this in iOS 7 and before, but it required a lot of hoops to jump through and also could make for a somewhat confusing user experience.

In iOS 8, however, we have streamlined this API.

All it is is simple additions on top of the UILocalNotification API class.

And what you can do is define core location region objects and attach them to this notification so that the notification will fire when the user happens to come near, enter or exit a region.

Now, you can make it so that these notifications are presented only the very first time that the user happens to enter this region.

Or you could have it fire always if that makes sense for your app.

And, again, since this feature is so tightly integrated with core location, it does require a little bit of core location registration on your part.

So, let's take a look at what that registration code is before we get into how we can actually schedule these notifications.

So, here we are.

What we need to do is create a CLLocationManager instance.

Then we just need to set the delegate on this manager.

The delegate is going to receive callbacks notifying whether your app is allowed to or not allowed to track the user's location.

And then finally, in order to enable these location-based notifications, on the location manager instance you need to call requestWhenInUseAuthorization.

So, what does this mean?

WhenInUseAuthorization -essentially, if the user says OK, will allow your app to track the user's location or know about the user's location when your app is running in the foreground.

However, recall these notifications are going to be appearing on the user's device even if your app is in the background or suspended.

And they might be able to see these alerts.

Well, that's OK because even if your app has been disabled for core location, and even if the user is seeing those alerts, your app won't be receiving any callbacks until the user actually interacts with that alert and your app is still allowed to track the user's location.

So we're requesting our WhenInUseAuthorization from CLLocationManager, assuming this is the very first time that your app has called this code, the user is going to be presented with a permission alert, just basically saying is it OK for this app to track your location when it's running in the foreground.

Notice, however, in that alert, we've got that usage text down below in the smaller font.

This is actually something that our app has defined on its own.

And you need to make sure that your app defines this usage text as well.

So to do that, in your info.plist file, hopefully this makes it easier to read, we've got NSLocationWhenvI nUseUsageDescription.

You've just got to define this key.

The value is going to be a string.

And this is the actual usage text that's going to appear in that alert.

Recall, however, that if your app is running in different locales in different languages, you need to make sure that this string is localized appropriately for all those other languages.

So, make sure that you define values for this key in your info.plist strings file as well.

So, now we've asked the user if it's OK for your app to track their location when it's running in the foreground.

Now we actually need to handle the callback from CLLocationManager.

And to do this, your manager's delegate is going to receive this callback LocationManagerDid hangeAuthorizationStatus.

At that point, all you need to do is just make sure the status is the When in Use status if you are authorized for tracking the user's location when in use.

Then at that point you can start scheduling these location-based notifications.

So, how do we actually schedule these location-based notifications?

Let's take a look at some sample code of how we could schedule a notification that triggers in response to the user entering a region.

Very first thing you need to do, just like any other UI local notification that would otherwise be triggered by a date or a time, you've first got to create an instance of UILocalNotification and define what type of notification this is going to be.

In this case, we're just saying this is going to be an alert.

When the user happens to enter that region, assuming the app isn't running in the foreground, they're going to get a little popup saying: Hey, you have arrived.

Then, specific to region type, core location type, user UI local notifications, we're stating here that we only want this notification to trigger the very first time the user happens to enter or exit this region.

Now this is actually the default behavior.

So, it's a little bit superfluous here.

However, you could set this to No if that makes sense for your users and for your app.

Next, you just need to create a CL region instance and set it on the region property of the UI local notification.

So, in this case, we're defining a CLCircularRegion here, and we're just giving it some arbitrary coordinate with some radius so that when the user enters this circle, this notification is going to be triggered.

However, I did say that this is a CL region property.

So, you could also use CL beacon regions or any other type of CL region subclass.

And if you want to find out more about how you can use Core Location, especially in combination with UILocalNotification, I've got some resources to point you towards at the end of this talk.

Finally, on your UIApplication shared instance, you just need to call scheduleLocalNotification, passing this notification just like you would any other user-type local notification.

So, cool. Now we've actually got this notification scheduled.

Assuming that your app is running in the background or suspended, rather, and the user happens to enter into that region, they're going to be presented with an alert saying: Hey, you've arrived at your destination.

And your app can handle that local notification in the applicationDidFinish LaunchingWithOptions.

Alternatively, if your app is running in the foreground when the user happens to enter into that region, your app delegate is going to be called back with applicationDidReceive LocalNotification.

So, the two different methods here, applicationDid FInishLaunching versus applicationDidReceive LocalNotification, the logic is very, very similar.

So let's just take a look at the latter step, or the latter part.

So, we've been informed that the user has entered into a region, or rather that the user has received a local notification, and we want to check whether this is actually region-based notification.

Well, UILocalNotification has a region property now to see if that region happens to not be nil.

And if it isn't, we've got a location-based notification.

And we can do whatever makes sense.

Tell all the user's friends where they've arrived.

So, that's location-based notifications.

It's very, very simple API that's added onto UI LocalNotification.

And it's so simple because we've integrated directly with core location.

However, because we've integrated this with Core Location, we do require some Core Location registration logic.

Now, again, this is all as well about keeping the user's privacy first place in mind.

So, if the user happens to have ever disabled your app from being able to track their location, even when your app is in the foreground, you're not going to be receiving callbacks like applicationDidReceive LocalNotification for location-based notifications.

The user might launch your app in response to an alert that was presented as a location-based notification.

But still, your app isn't going to know that.

And that was a lot of stuff that we talked about today.

Biggest thing, we've been talking about notification actions.

Rhett came up here, talked about this great new feature for iOS 8.

So psyched to see you guys use it, making your apps interactive, even when they're not running in the foreground, in really new and powerful ways.

Some simple changes behind user and remote notification registration.

Again, we've separated the concept of having to register for different remote notification types and instead ask you to register for the user notification types that your app is going to use.

And then we had location-based notifications, integrating tightly with Core Location to schedule user notifications in response to the user entering or exiting regions.

So, that was a lot of stuff.

And we've got great resources for you guys to check out.

Paul Danbold, he's our Core OS Technologies Evangelist.

He is a great guy.

And you can send him letters at danbold@apple.com.

We've also got documentation at developer@apple.com as well the dev forums.

Talk to like-minded developers.

Find out how other people are using these great new features.

Ask your questions.

Get them answered.

But, but, but-this is WWDC.

And we've also got other sessions.

Now, these sessions happened previously.

What's New in Core Location as well as Taking Core Location Indoors happened yesterday, but these are available online as well as Protecting the User's Data.

Rhett hinted at that data class protection.

Well, in 2012 we had a session on these as well.

And you can check out these videos online, too.

So, you guys have been great.

Thank you so much for coming to WWDC.

Hope you have a great rest of your week.

[ Applause ]

Apple, Inc. AAPL
1 Infinite Loop Cupertino CA 95014 US