Setting up Pushwoosh InboxKit iOS
यह सामग्री अभी तक आपकी भाषा में उपलब्ध नहीं है।
Available since iOS SDK 7.0.40.
Pushwoosh InboxKit ships a modern UIKit inbox screen on top of the existing inbox backend. Three default cell layouts cover the common Braze-style content card shapes, inline CTA buttons handle the most common interactions, and the entire surface is open for subclassing if you need a bespoke look.

Default InboxKit feed with banner, captioned, and classic cards.
When to use InboxKit
Anchor link toUse InboxKit for any new iOS integration. It is the recommended replacement for the older Objective-C PushwooshInboxUI module.
InboxKit gives you:
- Three built-in cell types — banner, captioned, classic — selected per message via
actionParams["displayType"]from your push payload, or forced from code viaattributes.forceCellKind. - Inline CTA buttons with a typed
PushwooshInboxButtonActionenum (openURL,dismiss,markRead,custom). The SDK handles the first three automatically; your delegate routescustomto your own logic. - Pinning support: messages with
actionParams["pinned"] == truefloat to the top of the feed and render a pin glyph. - Swipe-to-delete, pull-to-refresh, automatic mark-as-read on disappear — all toggleable via
PushwooshInboxKitAttributes. - Persistent storage: deletes and read state survive a process restart even if the network call has not been acknowledged yet.
- An open
PushwooshInboxCellbase class for fully custom layouts.
The server contract is unchanged — the same Pushwoosh inbox backend, payloads, and dashboard tooling work as before.
Choose your integration method
Anchor link to- Set up InboxKit with Swift Package Manager — recommended for new projects.
- Set up InboxKit with CocoaPods — for projects already using CocoaPods.
Read custom data from a message
Anchor link toTo make a push appear in the inbox, the Messages API createMessage request must include inbox_image, inbox_date, or inbox_days — without one of those fields the push is delivered as a regular notification and never reaches the inbox feed. Free-form custom data goes under the data key, which the SDK delivers to the client as the u parameter:
{ "request": { "application": "XXXXX-XXXXX", "auth": "API_TOKEN", "notifications": [{ "send_date": "now", "ios_title": "Summer sale", "content": "30% off everything — limited time only", "inbox_image": "https://cdn.example.com/inbox/summer.png", "inbox_days": 7, "data": { "promo_id": "SUMMER2026", "screen": "promo_details" }, "ios_root_params": { "displayType": "captioned" }, "platforms": [1] }] }}The SDK exposes that object on the inbox message through actionParams. Read it from the delegate when the user taps the row or an inline CTA:
extension MyInboxHost: PushwooshInboxKitDelegate {
func inboxKit(_ vc: PushwooshInboxKitViewController, didSelect message: PWInboxMessageProtocol) -> Bool { guard let params = message.actionParams as? [String: Any] else { return true }
// The custom `data` object arrives under the "u" key — // either as a nested dictionary or as a JSON-encoded string, // depending on how the payload was built upstream. let custom: [String: Any]? = { if let dict = params["u"] as? [String: Any] { return dict } if let raw = params["u"] as? String, let bytes = raw.data(using: .utf8), let parsed = try? JSONSerialization.jsonObject(with: bytes) as? [String: Any] { return parsed } return nil }()
if let promoId = custom?["promo_id"] as? String { navigateToPromo(promoId) return false // we handled the tap; SDK should not run the default action } return true }}The same actionParams["u"] lookup works inside inboxKit(_:didTapButton:onMessage:) for inline CTA buttons. For the typed CTA cases (openURL, dismiss, markRead) the SDK already performs the default action — return true to keep that behavior, or false to suppress it and run your own.
Add inline CTA buttons
Anchor link toA message can carry up to three inline call-to-action buttons. Buttons live alongside other custom data inside data as a buttons array. The SDK auto-renders them inside the captioned and classic cells:
{ "request": { "application": "XXXXX-XXXXX", "auth": "API_TOKEN", "notifications": [{ "send_date": "now", "ios_title": "New promo card", "content": "Tap a button to claim or save", "inbox_image": "https://cdn.example.com/inbox/promo.png", "inbox_days": 7, "data": { "promo_id": "SUMMER2026", "buttons": [ { "title": "Claim", "url": "https://example.com/promo/SUMMER2026" }, { "title": "Read", "action": "markRead" }, { "title": "Save", "action": "custom", "tag": "save_promo" } ] }, "ios_root_params": { "displayType": "captioned" }, "platforms": [1] }] }}Each button object has these fields:
| Field | Type | When |
|---|---|---|
title | string | Required. Visible button label. |
url | string | A non-empty parseable URL produces an openURL action. The SDK opens it via UIApplication.shared.open unless your delegate suppresses it. |
action | string | Explicit action token: dismiss (removes the message from the feed), markRead (marks the message read), or custom (host-handled). Case-insensitive. |
| Anything else | any | When action is custom, every key on the button object except title and action is forwarded to your delegate as the custom payload — agree on a key with the marketer (e.g. tag) and dispatch on it. |
Resolution priority: explicit action token first, then url if non-empty, otherwise the button falls into custom carrying the full payload (minus title and action).
Intercept taps from your delegate. The button.action property is the typed PushwooshInboxButtonAction enum:
extension MyInboxHost: PushwooshInboxKitDelegate {
func inboxKit(_ vc: PushwooshInboxKitViewController, didTapButton button: PushwooshInboxButton, onMessage message: PWInboxMessageProtocol) -> Bool { switch button.action { case .openURL(let url): // Default behavior is fine — let SDK open the URL. return true
case .dismiss, .markRead: // SDK handles both. Return false if you want to override. return true
case .custom(let payload): // Marketer-defined custom button. Dispatch on a key you agreed on. if let tag = payload["tag"] as? String { switch tag { case "save_promo": saveCurrentPromoLocally(message: message) default: break } } return true // ignored for custom — SDK never runs a default action here } }}