iOS Integration Best Practices for Swift and Objective-C

Push Notification Behavior

Push notifications received outside of the app are handled directly by the operating system. Your app can only communicate with the notification in the following scenarios:

  • When a user taps the notification to launch the app.
  • When a notification is received while the app is open.

Working with push notifications

The Urban Airship SDK makes use of a number of the AppDelegate's notification handling methods. To ensure that there are no conflicts within your app, please do not expose or override any of following methods:

  • application didRegisterForRemoteNotificationsWithDeviceToken
  • application didRegisterUserNotificationSettings
  • application didFailToRegisterForRemoteNotificationsWithError
  • application didReceiveRemoteNotification
  • application didReceiveRemoteNotification application handleActionWithIdentifier 

Instead, to handle notifications you should create a custom push notification handler class that implements the UAPushNotificationDelegate protocol. 

Swift Example:

import AirshipKit

class CustomNotificationHandler: NSObject, UAPushNotificationDelegate {
    func receivedBackgroundNotification(_ notificationContent: UANotificationContent, completionHandler: @escaping (UIBackgroundFetchResult) -> Swift.Void) {
        // Background content-available notification
        NSLog("The application received a background notification");

        // Call the completion handler
        completionHandler(.noData)
    }
    
    func receivedForegroundNotification(_ notificationContent: UANotificationContent, completionHandler: @escaping () -> Swift.Void) {
        // Foreground notification
        NSLog("The application received a foreground notification");

        completionHandler()
    }
    
    func receivedNotificationResponse(_ notificationResponse: UANotificationResponse, completionHandler: @escaping () -> Void) {
        // Notification response
        NSLog("Received a notification response");
        
        completionHandler()
    }
    
    @available(iOS 10.0, *)
    func presentationOptions(for notification: UNNotification) -> UNNotificationPresentationOptions {
        // iOS 10 foreground presentation options
        return [.alert, .sound]
    }
}

 

Objective-C Example:

@implementation CustomNotificationHandler

-(void)receivedBackgroundNotification:(UANotificationContent *)notificationContent completionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    // Background content-available notification
    NSLog(@"Received a background notification");
    
    // Call the completion handler
    completionHandler(UIBackgroundFetchResultNoData);
}

-(void)receivedForegroundNotification:(UANotificationContent *)notificationContent completionHandler:(void (^)())completionHandler {
    // Foreground notification
    NSLog(@"Received a notification response");
    
    completionHandler();
}

-(void)receivedNotificationResponse:(UANotificationResponse *)notificationResponse completionHandler:(void (^)())completionHandler {
    // Notification response
    NSLog(@"Received a notification response");
    
    completionHandler();
}

- (UNNotificationPresentationOptions)presentationOptionsForNotification:(UNNotification *)notification {
    // iOS 10 foreground presentation options
    return UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionSound;
}

@end

 

Then in your AppDelegate you can create an instance of this class and declare it as the pushNotificationDelegate:

Swift Example: 

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    /* Create a custom push notification handler property */
    var customPushHandler = CustomNotificationHandler()
    
    /* Set your custom nofication handler as the SDKs pushNotificationDelegate */
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
      
      UAirship.push().pushNotificationDelegate = customPushHandler
    }
}

 

Objective-C Example: 

#import "CustomNotificationHandler.h"

@interface AppDelegate ()

@property (strong, nonatomic) CustomNotificationHandler *customPushHandler;

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    self.customPushHandler = [[CustomNotificationHandler alloc] init];
    [UAirship push].pushNotificationDelegate = self.customPushHandler;

}

 

The Push Payload

Now that your custom notification handler is set up, you're going to want to work with the payload data sent with the push message. The payload is structured in a dictionary format that's easy to work with. For example, working with notification within the launchedFromNotification method to trigger a deep link.

 

Swift Example:

func launchedFromNotification(notification: [NSObject : AnyObject], fetchCompletionHandler completionHandler: ((UIBackgroundFetchResult) -> Void)) {
    NSLog("UALib: %@", "The application was launched or resumed from a notification: \(notification)");
    
    // Do something when launched via a notification
    
    for (key, value) in notification {
        
        if key == "^d" {
            // do something with a deep link value here
            print("Deep Link Found: \(value)")
        }
    }
    
    completionHandler(UIBackgroundFetchResult.NoData)
}

 

Objective-C Example:

-(void) launchedFromNotification:(NSDictionary *)notification fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    
    if ([notification objectForKey:@"^d"]) {
        // Do something with the deep link
        NSLog(@"Deep Link Found: %@", [notification valueForKey:@"^d"]);
    }
    
    completionHandler(UIBackgroundFetchResultNoData);
}

 

There are a number of dictionary items to work with, however the most common items are deep links or custom key/value pairs (we call these extras).

Example Payload: 

[com.urbanairship.in_app: {
  actions = {
    "button_actions" = {
      yes = {
        "^+t" = (
          tag2
        );
        "^u" = "https://google.com";
      };
    };
    "button_group" = "ua_yes_no_foreground";
    "on_click" = {
      "^+t" = (
        tag1
      );
      "^d" = "app://deepLinkPage";
    };
  };
  display = {
    alert = "In-App Message Goes Here";
    position = bottom;
    type = banner;
  };
  expiry = "2015-12-03T13:42:15";
}, 
_: XXXXXXXXXXXXX, 
aps: {
  alert = {
    body = "Push Message Goes Here";
    title = "Watch Message Text";
  };
  badge = 1;
  category = "ua_yes_no_foreground";
  "content-available" = 1;
  sound = default;
}, 
someKey: someValue, 
^+t: (
  tag1
), 
com.urbanairship.interactive_actions: {
  yes = {
    "^+t" = (
      tag2
    );
    "^u" = "https://google.com";
  };
}, 
^d: app://deepLinkPage
]

 

Key Descriptions:

Dictionary Item Description

com.urbanairship.in_app

A dictionary containing items related to in-app Messages.

display

Another dictionary containing:

  • the alert
  • the message position
  • the type (currently only banner)
  actions

Actions to take when interacting with button_actions on the in-app message.
These include:

  • adding a tag ^+t
  • loading an external URL ^u
  • triggering a deep link ^d.
See Action Mappings for more information on the short names.
  expiry The expiry time of the in-app message.

aps

Adictionary of items related to the push notification.

alert

The message to display.
If Apple Watch is also targeted the Watch message is displayed under title and the iOS message is displayed under body.

  badge The badge number.
  sound The app sound to play.
  content-available Specifies that there is additional content that should be downloaded with the app in background (extras, in-app message information etc.).
com.urbanairship.interactive_actions

^+t

Adds a tag.

A dictionary of items related to interactive notifications.

^-t Removes a tag.
  ^u Loads the specified external URL.
  ^d Triggers a deep link action.

 

In addition, your message can include your own custom key/value pairs. For example:

  • someKey1, someValue1
  • campaignID, ABCD12345

 

Related Content