iOS - Implementing Remote Notifications
In this page you'll learn how notifications are handled in your app and what are all the options at your disposal to create a great messaging experience for your users.
Notificare supports several types of interactive and actionable notifications that will be handled for you without any extra development. If you are going to prevent this default behaviour, please note that you will have to either handle all the functionality yourself (metrics logging, presenting UI or collect replies) or if you don't, you understand that some features will not work as advertised.
Enabling Notifications
In order to enable the device to receive notifications, all that you need to do is invoke a single method.
Notificare.shared.push().enableRemoteNotifications { result in
}
Typically, the step above is done during some form of user onboarding. When the user already went through that flow, we automatically enable notifications when Notificare launches.
You can also check whether the user enrolled on remote notifications.
Notificare.shared.push().hasRemoteNotificationsEnabled
Additionally, you can check if the user has disabled notifications in the System Settings.
Notificare.shared.push().allowedUI
Disabling remote notifications
Disabling remote notifications can be achieved in the same fashion as enabling them.
Notificare.shared.push().disableRemoteNotifications { result in
}
When this method is called, we will automatically register your device to never receive remote notifications, although you will still maintain the same user profile, inbox messages and enjoy all the other services your plan supports. You can at anytime request a re-register for push notifications if you wish to.
Receiving Notifications
Before you can start receiving push notifications, you will need to set the capabilities in your project. Go to your app's target (in the Apple Developer Portal), click in the tab Capabilities and add both Push Notifications and Background Modes / Remote Notifications as shown below.
Authorization options
Our SDK allows you to define which notification's authorization options you would like to request from your user. This is an optional step, if not defined we will register UNAuthorizationOptions.alert
, UNAuthorizationOptions.badge
and UNAuthorizationOptions.sound
by default. To define authorization options please add the following to your AppDelegate
and customise as needed:
if #available(iOS 13.0, *) {
Notificare.shared.push().authorizationOptions = [.alert, .badge, .sound, .providesAppNotificationSettings, .provisional, .announcement]
} else if #available(iOS 12.0, *) {
Notificare.shared.push().authorizationOptions = [.alert, .badge, .sound, .providesAppNotificationSettings, .provisional]
} else {
Notificare.shared.push().authorizationOptions = [.alert, .badge, .sound]
}
Please note the following authorization options are available: UNAuthorizationOptions.announcement
first introduced in iOS 13. The options UNAuthorizationOptions.providesAppNotificationSettings
and UNAuthorizationOptions.provisional
are available since iOS 12. The option UNAuthorizationOptions.announcement
will allow Siri to automatically read out messages over AirPods, the UNAuthorizationOptions.provisional
option will register for notifications with provisional authorization, this means that users will not be prompted to with the permission dialog to accept notifications. Although this might be a great way to opt-in users to remote notifications, any message you sent afterwards will be delivered quietly. Messages delivered quietly will not be shown in the lock screen or play a sound.
Also note that if you implement the UNAuthorizationOptions.providesAppNotificationSettings
option, notifications from your app will display a button in both the Instant Tuning menu and Notification Settings. The purpose of that button is to provide users a shortcut to your app settings where they can fine-tune which kind of notifications they would like to receive. Implementing such settings views is highly recommended as it could be the reason between allowing your app to keep display notifications or being mute completely. If you do implement this option it is mandatory that you implement the following NotificarePushDelegate
method:
func notificare(_ notificare: NotificarePush, shouldOpenSettings notification: NotificareNotification?) {
// Deep link to your settings view.
}
This will give you the opportunity to present your users with the in-app settings view where you should allow them to customize what kind of notifications they should receive. If the user clicked the button from a specific notification, you will receive that object too. When it comes from the Notification Settings, that object will be nil.
Presentation options
Optionally, you can enable presentation options when your app is in the foreground. This will allow you to show a small banner on the top of your app, play a sound or badge your app, whenever a notification arrives, and your app is being used. By default, our library will set this to UNNotificationPresentationOptions = [], but you can change this behaviour to match your needs:
if #available(iOS 14.0, *) {
Notificare.shared.push().presentationOptions = [.banner, .sound, .badge]
} else {
Notificare.shared.push().presentationOptions = [.alert, .sound, .badge]
}
Listening to Received Notifications
Once you're receiving notifications in your app, we can dive deeper and fully understand how they are handled. If you want to be notified incoming notifications in your NotificarePushDelegate
instance, for example to add a badge to in your application, you can implement the following method.
extension AppDelegate: NotificarePushDelegate {
func notificare(_ notificare: NotificarePush, didReceiveNotification notification: NotificareNotification, deliveryMechanism: NotificareNotificationDeliveryMechanism) {
}
}
Presenting notifications
A notification can be opened by either tapping the actual notification or by tapping an action inside the notification. We will emit an event in each case to the NotificarePushDelegate
.
extension AppDelegate: NotificarePushDelegate {
func notificare(_ notificare: NotificarePush, didOpenNotification notification: NotificareNotification) {
}
func notificare(_ notificare: NotificarePush, didOpenAction action: NotificareNotification.Action, for notification: NotificareNotification) {
}
}
To handle the events above, you can take the managed approach and use our NotificarePushUI
module which takes care of all the events and UI types as well as actions, or you can fully take over and present them however you prefer. However, be aware if you take the non-managed approach as you will have to deal with all aspects and types of presenting the notifications, including the events needed to show the user's engagement in our Dashboard.
The first thing you need, to handle all types of notifications, is to make sure your app is declaring the following permissions in your app's Info.plist
file:
This will make sure your app can request access to the device's camera or photo library whenever it is needed.
The code below illustrates how this works when using the managed approach.
extension AppDelegate: NotificarePushDelegate {
func notificare(_ notificare: NotificarePush, didOpenNotification notification: NotificareNotification) {
let controller: UIViewController = /* find your desired controller to present the UI in */
Notificare.shared.pushUI().presentNotification(notification, in: controller)
}
func notificare(_ notificare: NotificarePush, didOpenAction action: NotificareNotification.Action, for notification: NotificareNotification) {
let controller: UIViewController = /* find your desired controller to present the UI in */
Notificare.shared.pushUI().presentAction(action, for: notification, in: controller)
}
}
Additionally, when using the managed approach, you can listen to Notification lifecycle events and perform any additional steps you may require. Let your AppDelegate
implement the NotificarePushUIDelegate
and add following methods as needed.
extension AppDelegate: NotificarePushUIDelegate {
// MARK: - Notifications
func notificare(_ notificare: NotificarePushUI, willPresentNotification notification: NotificareNotification) {
}
func notificare(_ notificare: NotificarePushUI, didPresentNotification notification: NotificareNotification) {
}
func notificare(_ notificare: NotificarePushUI, didFinishPresentingNotification notification: NotificareNotification) {
}
func notificare(_ notificare: NotificarePushUI, didFailToPresentNotification notification: NotificareNotification) {
}
func notificare(_ notificare: NotificarePushUI, didClickURL url: URL, in notification: NotificareNotification) {
}
// MARK: - Actions
func notificare(_ notificare: NotificarePushUI, willExecuteAction action: NotificareNotification.Action, for notification: NotificareNotification) {
}
func notificare(_ notificare: NotificarePushUI, didExecuteAction action: NotificareNotification.Action, for notification: NotificareNotification) {
}
func notificare(_ notificare: NotificarePushUI, didNotExecuteAction action: NotificareNotification.Action, for notification: NotificareNotification) {
}
func notificare(_ notificare: NotificarePushUI, didFailToExecuteAction action: NotificareNotification.Action, for notification: NotificareNotification, error: Error?) {
}
func notificare(_ notificare: NotificarePushUI, shouldPerformSelectorWithURL url: URL, in action: NotificareNotification.Action, for notification: NotificareNotification) {
}
}
If you are considering supporting non-HTTPS pages when using the Webpage notification type you will need to also declare a more permissive ATS policy as follows: