SDK

Remote Notifications

In this page you'll learn how notifications are handled in your app and what all the options at your disposal to create a great messaging experience for your users.

Notificare library accepts 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.

Receiving Notifications

Whenever a remote notification arrives a badge is placed on the top of your app's icon. Unlike iOS, tvOS does not provide a notification center so if an incoming notifications arrives and your app was killed the only way to handle it is from the launching options. To make sure you handle this correctly, you must implement the handleOptions method, in your AppDelegate.m or AppDelegate.swift as follows:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    ...more code

    [[NotificarePushLib shared] handleOptions:launchOptions];

    ...more code
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {

    ...more code

    if launchOptions != nil {
        NotificarePushLib.shared().handleOptions(launchOptions!)
    }

    ...more code
}

If your app is in background or foreground, when a notification arrives, iOS will trigger the following application delegate. Implement the following to make sure you handle this correctly:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{

    [[NotificarePushLib shared] handleNotification:userInfo forApplication:application completionHandler:^(NSDictionary *info) {

        completionHandler(UIBackgroundFetchResultNewData);

    } errorHandler:^(NSError *error) {

        completionHandler(UIBackgroundFetchResultNoData);

    }];
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    NotificarePushLib.shared().handleNotification(userInfo, for: application, completionHandler: {(_ info: [AnyHashable: Any]) -> Void in
        completionHandler(.newData)
    }, errorHandler: {(_ error: Error?) -> Void in
        completionHandler(.noData)
    })
}

The method above will make sure your app can handle silent notifications and that it can download content in response to a push notification. In tvOS when a user opens your app after a notifcation has arrived, this method will triggered. If more than one notification has arrived only the latest notification will trigger this delegate.

None of the methods above will show any content if the app is running on foreground. In most cases when your app is being used you will not want to interrupt the user by presenting content from an incoming notification. It is a good practice to instead use our inbox mechanisms to simply show a badge in your app and let the user see the unread messages from the inbox list. But if your use case requires you to actually present content whenever a notification is received, while the app is in the foreground, you can change that behaviour as shown below:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{

    [[NotificarePushLib shared] openNotification:userInfo];

}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

    NotificarePushLib.shared().openNotification(userInfo)

}

In modern apps, this is a great way of creating interactions between notifications and your own app content, allowing you to send messages that can eventually drive the user to open content hidden deeper in your app.

To prepare your app to handle deep links is not complicated and will allow you to handle not only Deep Link notification types, but also any link made from an web page. In order to indicate your app that you will handle a custom URL scheme you simply have to declare the following in your app's .plist file:

ios url schemes

Because these deep links can also be called from actions in your notifications, you must also declare it the Launch Services Queries Schemes in your app's .plist file as shown below:

ios launch services url schemes

Then in your AppDelegate.m or AppDelegate.swift make sure your implement the following methods:

-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{
    [[NotificarePushLib shared]  handleOpenURL:url];

    //Handle your deep linking

    return YES;
}
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    NotificarePushLib.shared().handleOpen(url)
    //Handle your deep linking
    return true
}

Inbox

With our library it's extremely easy to implement an in-app inbox. Implementing an inbox increases considerably the engagement rates of your notifications simply because messages will always be available inside your app. To activate the inbox functionality, please follow the instructions described here.

After activating this functionality you can start implementing your inbox in your app. To get all the items in the inbox you would basically invoke the following:

[[NotificarePushLib shared] fetchInbox:nil skip:nil limit:nil completionHandler:^(NSDictionary *info) {

    //By default we will give the last 25 messages
    //You can use skip and limit to change this default and create a paginator
    //Max. number of messages you can retrieve per page is 100
    NSArray * messages = [info objectForKey:@"inbox"];
    //This will be a list of NotificareDeviceInbox objects

    //Get the total number of messages in the inbox
    int total = [[info objectForKey:@"total"] intValue];

    //Get the total number of unread messages in the inbox
    int unread = [[info objectForKey:@"unread"] intValue];

} errorHandler:^(NSError *error) {
    //Handle error
}];
NotificarePushLib.shared().fetchInbox(nil, skip: nil, limit: nil, completionHandler: {(_ info: [AnyHashable: Any]) -> Void in
    //By default we will give the last 25 messages
    //You can use skip and limit to change this default and create a paginator
    //Max. number of messages you can retrieve per page is 100
    var messages = info["inbox"] as? [Any] ?? [Any]()
    //This will be a list of NotificareDeviceInbox objects
    //Get the total number of messages in the inbox
    var total = CInt(info["total"] as? Int ?? 0)
    //Get the total number of unread messages in the inbox
    var unread = CInt(info["unread"] as? Int ?? 0)
}, errorHandler: {(_ error: Error?) -> Void in
    //Handle error
})

To open a message from the list of messages in the inbox, please use the following method:

[[NotificarePushLib shared] openInboxItem:(NotificareDeviceInbox *)item];
NotificarePushLib.shared().openInboxItem((item as? NotificareDeviceInbox))

At anytime you can also delete a notification from the inbox:

[[NotificarePushLib shared] removeFromInbox:(NotificareDeviceInbox *)item completionHandler:^(NSDictionary *info) {

    //Reload your inbox

} errorHandler:^(NSError *error) {

    //Handle error
}];
NotificarePushLib.shared().remove(fromInbox: (item as? NotificareDeviceInbox), completionHandler: {(_ info: [AnyHashable: Any]) -> Void in
    //Reload your inbox
}, errorHandler: {(_ error: Error?) -> Void in
    //Handle error
})

Additionally you can also mark a message as read by invoking the following method:

[[NotificarePushLib shared] markAsRead:(NotificareDeviceInbox *)item completionHandler:^(NSDictionary *info) {

    //Reload your inbox

} errorHandler:^(NSError *error) {

    //Handle error
}];
NotificarePushLib.shared().mark(asRead: (item as? NotificareDeviceInbox), completionHandler: {(_ info: [AnyHashable: Any]) -> Void in
    //Reload your inbox
}, errorHandler: {(_ error: Error?) -> Void in
    //Handle error
})

Finally you can also delete all items in the inbox by invoking the following method:

[[[NotificarePushLib shared] clearInbox:^(NSDictionary *info) {

    //Reload your inbox

} errorHandler:^(NSError *error) {

    //Handle error
}];
NotificarePushLib.shared().clearInbox({(_ info: [AnyHashable: Any]) -> Void in
    //Reload your inbox
}, errorHandler: {(_ error: Error?) -> Void in
    //Handle error
})

If you've configured your inbox functionality to use the AutoBadge feature, then implement the following delegate in your AppDelegate.m or AppDelegate.swift:

- (void)notificarePushLib:(NotificarePushLib *)library didUpdateBadge:(int)badge{
    //Update UI or reload Inbox
}
func notificarePushLib(_ library: NotificarePushLib, didUpdateBadge badge: Int) {
    //Update UI or reload Inbox
}

If you using AutoBadge, you can also access your badge count of unread messages at any time by doing the following:

int badge = [[NotificarePushLib shared] myBadge];
var badge: Int = NotificarePushLib.shared().myBadge()

Notification Delegates

Optionally, you can implement delegate methods which can inform your app when certain operations are done or failed, so you can show more UX/UI elements, perform other operations, etc. In your AppDelegate.m or AppDelegate.swift you can add the following delegate methods:

- (void)notificarePushLib:(NotificarePushLib *)library willOpenNotification:(NotificareNotification *)notification{
    //Triggered whenever notification is about to be opened
}

- (void)notificarePushLib:(NotificarePushLib *)library didOpenNotification:(NotificareNotification *)notification{
    //Triggered when the notification does open
}

- (void)notificarePushLib:(NotificarePushLib *)library didCloseNotification:(NotificareNotification *)notification{
    //Triggered when the user closes the notification or completes an action
}

- (void)notificarePushLib:(NotificarePushLib *)library didFailToOpenNotification:(NotificareNotification *)notification{
    //Triggered when notification failed to open
}
func notificarePushLib(_ library: NotificarePushLib, willOpen notification: NotificareNotification) {
    //Triggered whenever notification is about to be opened
}

func notificarePushLib(_ library: NotificarePushLib, didOpen notification: NotificareNotification) {
    //Triggered when the notification does open
}

func notificarePushLib(_ library: NotificarePushLib, didClose notification: NotificareNotification) {
    //Triggered when the user closes the notification or completes an action
}

func notificarePushLib(_ library: NotificarePushLib, didFailToOpen notification: NotificareNotification) {
    //Triggered when notification failed to open
}

Actions Delegates

The same can be achieved for actions. In your AppDelegate.m or AppDelegate.swift you can add the following delegate methods:

- (void)notificarePushLib:(NotificarePushLib *)library willExecuteAction:(NotificareNotification *)notification{
    //Triggered just before the action is going to be executed
}

- (void)notificarePushLib:(NotificarePushLib *)library didExecuteAction:(NSDictionary *)info{
    //Triggered when the action is executed
}

-(void)notificarePushLib:(NotificarePushLib *)library shouldPerformSelectorWithURL:(NSURL *)url{
    //Required if you are going to use actions of type "Call a method in your app"
    //Handle it pretty much the same way you would handle a deep link
}

- (void)notificarePushLib:(NotificarePushLib *)library didNotExecuteAction:(NSDictionary *)info{
    //Triggered when the action sheet is cancelled
}

- (void)notificarePushLib:(NotificarePushLib *)library didFailToExecuteAction:(NSError *)error{
    //Triggered when an action failed to be executed
}
func notificarePushLib(_ library: NotificarePushLib, willExecuteAction notification: NotificareNotification) {
    //Triggered just before the action is going to be executed
}

func notificarePushLib(_ library: NotificarePushLib, didExecuteAction info: [AnyHashable: Any]) {
    //Triggered when the action is executed
}

func notificarePushLib(_ library: NotificarePushLib, shouldPerformSelectorWith url: URL) {
    //Required if you are going to use actions of type "Call a method in your app"
    //Handle it pretty much the same way you would handle a deep link
}

func notificarePushLib(_ library: NotificarePushLib, didNotExecuteAction info: [AnyHashable: Any]) {
    //Triggered when the action sheet is cancelled
}

func notificarePushLib(_ library: NotificarePushLib, didFailToExecuteAction error: Error?) {
    //Triggered when an action failed to be executed
}