Displaying a Message Center Message in a Custom Webview

This guide shows the minimum integration necessary to display a Message Center message in a custom webview.

While the Airship SDK provides built-in Message Center UI, sometimes it can be useful to create a custom implementation that bypasses the default implementation’s view hierarchy. Message Center messages are just HTML, and so they can be displayed in any webview. However, there are a few integration steps needed to ensure that authorization and the Native Bridge function properly.

Authentication and Loading

Message Center messages are fetched with basic authentication using the User credentials in base64 encoding. This class persists a unique username and password on the iOS Keychain, and provides easy access to the information at runtime without needing to deal with the Keychain directly.

The example below shows how to fetch the credentials, set auth on the request, and load a message into the webview. This code assumes a custom view controller with an embedded WKWebView, as well as a InboxMessage ready to be loaded.

NSMutableURLRequest *requestObj = [NSMutableURLRequest requestWithURL:self.message.messageBodyURL];

[MessageCenter.shared.user getUserData:^(UAUserData *userData) {
   NSString *auth = [UAUtils authHeaderStringWithName:userData.username password:userData.password];
   [requestObj setValue:auth forHTTPHeaderField:@"Authorization"];

   // load the request
   [self.webView loadRequest:requestObj];
} queue:dispatch_get_main_queue()];
let requestObj = NSMutableURLRequest(url:self.message.messageURL)
MessageCenter.shared.user.getData { data in
   // set the auth
   let auth = Utils.authHeaderString(withName: data.username, password: data.password)
   requestObj.setValue(auth, forHTTPHeaderField:"Authorization")

   // load the request
}, queue: DispatchQueue.main)

Setting up the Native Bridge

The Airship Native bridge works by intercepting all links with the uairship:// scheme and translating specially URL-encoded paths into native commands and arguments. In order to do this in a custom webview, the view controller containing the webview (or whichever class acts as the WKNavigationDelegate) must delegate navigation handling to the Native Bridge. To continue to receive these events, the original delegate can sign up as a “forward delegate”, by implementing the WKNavigationDelegate protocol. This allows the Native Bridge to forward WKNavigationDelegate calls to the original delegate. The example code below shows how to do this, and assumes both native bridge property in the view controller, and the view controller implement WKNavigationDelegate

- (void)viewDidLoad {
   [super viewDidLoad];

   // allow native bridge to intercept links
   self.nativeBridge = [[UANativeBridge alloc] init];
   self.webView.navigationDelegate = self.nativeBridge;

   // forward navigation events back to self
   self.nativeBridge.forwardDelegate = self;

override func viewDidLoad() {

   // allow native bridge to intercept links
   self.nativeBridge = NativeBridge()
   self.webView.navigationDelegate = self.nativeBridge

   // forward navigation events back to self
   self.nativeBridge.forwardDelegate = self

Enabling the Close Command

Among other commands, the Native Bridge also exposes a UAirship.close() command to the JavaScript layer, which makes it possible for elements or JavaScript routines in the message to close the containing message view. This is optional functionality, but if you would like to add this capability to your app, you will need to implement an additional UANativeBridgeDelegate method in the view controller containing your webview.

- (void)closeWindowAnimated:(BOOL)animated {
   // dismiss the webview here
override func closeWindow(animated: Bool) {
   // dismiss the webview here