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 receivedForegroundNotification(notification: [NSObject : AnyObject], fetchCompletionHandler completionHandler: ((UIBackgroundFetchResult) -> Void)) {
        NSLog("UALib: %@", "Received a notification while the app was already in the foreground: \(notification)")
        
        /*
        Called when a push is received when the app is in the foreground
        You can work with the notification object here
        
        Be sure to call the completion handler with a UIBackgroundFetchResult
        */
        completionHandler(UIBackgroundFetchResult.NoData)
    }
    
    func launchedFromNotification(notification: [NSObject : AnyObject], fetchCompletionHandler completionHandler: ((UIBackgroundFetchResult) -> Void)) {
        NSLog("UALib: %@", "The application was launched or resumed from a notification: \(notification)");
        
        /*
        Called when the app is launched/resumed by interacting with the notification
        You can work with the notification object here
        
        Be sure to call the completion handler with a UIBackgroundFetchResult
        */
        completionHandler(UIBackgroundFetchResult.NoData)
    }

    
    func receivedBackgroundNotification(notification: [NSObject : AnyObject], actionIdentifier identifier: String, completionHandler: () -> Void) {
        NSLog("UALib: %@", "The application was started in the background from a user notification button");
        
        /*
        Called when the app is launched/resumed by interacting with a notification button
        You can work with the notification object here
        */
        
        completionHandler()
    }
    
    func receivedBackgroundNotification(notification: [NSObject : AnyObject], fetchCompletionHandler completionHandler: ((UIBackgroundFetchResult) -> Void)) {
        NSLog("UALib: %@", "A CONTENT_AVAILABLE notification was received with the app in the background: \(notification)");
        /*
        Called when the app is in the background and a CONTENT_AVAILABLE notification is received
        Do something with the notification in the background
        
        Be sure to call the completion handler with a UIBackgroundFetchResult
        */
        completionHandler(UIBackgroundFetchResult.NoData)
    }
}

 

Objective-C Example:

@implementation CustomNotificationHandler

-(void) receivedForegroundNotification:(NSDictionary *)notification fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
    NSLog(@"Received a notification while the app was already in the foreground: %@", notification);
    
    // Called when a push is received when the app is in the foreground
    // You can work with the notification object here

    // Be sure to call the completion handler with a UIBackgroundFetchResult
    
    
    completionHandler(UIBackgroundFetchResultNoData);
    
}

-(void) launchedFromNotification:(NSDictionary *)notification fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    NSLog(@"The application was launched or resumed from a notification: %@", notification);
    
    // Called when the app is launched/resumed by interacting with the notification
    // You can work with the notification object here

    // Be sure to call the completion handler with a UIBackgroundFetchResult
    
    completionHandler(UIBackgroundFetchResultNoData);
}

- (void)receivedBackgroundNotification:(NSDictionary *)notification actionIdentifier:(NSString *)identifier completionHandler:(void (^)())completionHandler {
    UA_LDEBUG(@"The application was started in the background from a user notification button");
    
    // Called when the app is launched/resumed by interacting with a notification button
    // You can work with the notification object here
    
    completionHandler();
}

-(void) receivedBackgroundNotification:(NSDictionary *)notification fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    NSLog(@"A CONTENT_AVAILABLE notification was received with the app in the background: %@", notification);
    
    // Called when the app is in the background and a CONTENT_AVAILABLE notification is received
    // Do something with the notification in the background

    // Be sure to call the completion handler with a UIBackgroundFetchResult
    
    completionHandler(UIBackgroundFetchResultNoData);
}

@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:

DictionaryItemDescription

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