Build a custom Message Center
Build a custom Message Center by composing the SDK’s ready-to-use views, handling display requests, integrating with your navigation, and filtering messages.
By default, Airship displays the Message Center as an overlay on top of your app. For tighter integration with your app’s navigation, build your own Message Center from the ready-to-use views the SDK provides. Each view is a SwiftUI View you can place anywhere in your app, style, and drive with your own navigation.
Ready-to-use views
The SDK provides a view for each part of the Message Center. Use the highest-level view that fits your needs, and drop to the lower-level views when you need more control.
| View | Use it to |
|---|---|
| Inbox view | Show the complete Message Center, either as an all-in-one view with its own navigation or as content you place inside your own navigation. |
| List view | Show only the message list, with or without a navigation bar. |
| Message view | Show a single message, with or without a navigation bar, or render only the message body. |
Every view reads its appearance from the global MessageCenterTheme. For colors, fonts, and icons, see Applying a custom theme.
Handling display requests
A push notification with a Message Center action, or a call to Airship.messageCenter.display(), triggers a display request. To route these requests to your own UI instead of the default overlay, set the display callbacks after takeOff.
Custom display handling
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
try! Airship.takeOff(config, launchOptions: launchOptions)
// Navigate to your custom UI when a message should be displayed
Airship.messageCenter.onDisplay = { messageID in
// messageID is optional - nil means show the full list
// Return true to prevent the default SDK display
return true
}
// Dismiss your custom UI when the Message Center should close
Airship.messageCenter.onDismissDisplay = {
// Dismiss your custom Message Center UI
}
return true
}- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[UAirship takeOff:config launchOptions:launchOptions error:nil];
UAirship.messageCenter.onDisplay = ^BOOL(NSString * _Nullable messageID) {
// Return YES to prevent the default SDK display
return YES;
};
UAirship.messageCenter.onDismissDisplay = ^{
// Dismiss your custom Message Center UI
};
return YES;
}Filtering messages
Set a predicate to control which messages appear. The SDK evaluates the predicate against every message and displays only those that pass. Apply a predicate globally on Airship.messageCenter, or pass one to an individual view.
Implement MessageCenterPredicate and return true for messages to keep:
public protocol MessageCenterPredicate: Sendable {
func evaluate(message: MessageCenterMessage) -> Bool
}Filter by named user
If multiple users share a device, filter the inbox to the current named user. When you create a message, include a custom key named named_user_id set to the user’s ID. See Add custom keys or the extra object in the Message Center object.
Filter by named user
class NamedUserPredicate: MessageCenterPredicate {
func evaluate(message: MessageCenterMessage) -> Bool {
guard let namedUserID = Airship.contact.namedUserID else {
return false
}
if let extras = message.extras,
let messageNamedUserID = extras["named_user_id"] as? String {
return messageNamedUserID == namedUserID
}
return false
}
}
Airship.messageCenter.predicate = NamedUserPredicate()// Not supported. Filtering requires a Swift implementation.To filter a single embedded view instead of the whole app, pass the predicate to the view. See the inbox view and list view pages.
Key components
- MessageCenter
- The main entry point for fetching messages and handling display callbacks. Access it through
Airship.messageCenter. - MessageCenterInboxProtocol
- Retrieves messages asynchronously and exposes the local message array. Access it through
Airship.messageCenter.inbox. - MessageCenterMessage
- A model object representing an individual message. A message’s content is either a web body or a native (SceneA mobile app or web experience of one or more screens displayed with fully native UI components in real time, providing immediate, contextual responses to user behaviors. Scenes can be presented in full-screen, modal, or embedded format using the default swipe/click mode or as a story. Scene content can also be displayed in a Message Center message and contain survey questions.) layout. Don’t load the body directly—render it with
MessageCenterMessageVieworMessageCenterMessageContentView, which resolve content type and authentication for both. - MessageCenterMessageContentView
- Renders only a message’s content—no loading indicator, error/retry UI, or mark-as-read. Available since SDK 20.10.0. See Rendering message content.
- MessageCenterController
- Shared state that binds the list and message views together and drives navigation. Pass one controller to the views that need to stay in sync.
The message list uses CoreData. Message objects are ephemeral references that refresh with the list. Don’t hold onto individual message instances indefinitely.