Перейти к содержанию

Настройка Pushwoosh InboxKit для iOS

Доступно с iOS SDK 7.0.40.

Pushwoosh InboxKit предоставляет современный экран входящих сообщений на базе UIKit поверх существующего бэкенда для входящих сообщений. Шесть стандартных макетов ячеек охватывают распространённые формы карточек контента — от простых баннеров до каруселей изображений, встроенного видео и пропусков Apple Wallet. Встроенные CTA-кнопки обрабатывают самые распространённые взаимодействия, а весь интерфейс открыт для создания подклассов, если вам нужен индивидуальный дизайн.

Лента InboxKit с карточками баннер, с подписью, классическая, карусель, видео и Apple Wallet

Стандартная лента InboxKit с карточками баннер, с подписью, классическая, карусель, видео и Apple Wallet.

Когда использовать InboxKit

Anchor link to

Используйте InboxKit для любой новой интеграции с iOS. Это рекомендуемая замена для устаревшего модуля PushwooshInboxUI на Objective-C.

InboxKit предоставляет вам:

  • Шесть встроенных типов ячеек — баннер, с подписью, классическая, карусель, видео и Apple Wallet — выбираются для каждого сообщения через displayType в полезной нагрузке или принудительно устанавливаются из кода через attributes.forceCellKind. Полный список см. в разделе Типы карточек. (Карточка Apple Wallet доступна только на iOS.)
  • Встроенные CTA-кнопки с типизированным перечислением PushwooshInboxButtonAction (openURL, dismiss, markRead, custom). SDK автоматически обрабатывает первые три. Ваш делегат направляет custom в вашу собственную логику.
  • Поддержка закрепления: сообщения с actionParams["pinned"] == true поднимаются в верхнюю часть ленты и отображают значок булавки.
  • Свайп для удаления, потяните для обновления, автоматическая отметка как прочитанное при исчезновении — всё это можно переключать через PushwooshInboxKitAttributes.
  • Постоянное хранилище: удаления и состояние прочтения сохраняются после перезапуска процесса, даже если сетевой вызов ещё не был подтверждён.
  • Открытый базовый класс PushwooshInboxCell для полностью настраиваемых макетов.

Серверный контракт не изменился — тот же бэкенд для входящих сообщений Pushwoosh, полезные нагрузки и инструменты панели управления работают, как и раньше.

Выберите способ интеграции

Anchor link to

Типы карточек

Anchor link to

InboxKit выбирает макет ячейки для каждого сообщения. Стандартный резолвер читает displayType из полезной нагрузки пуша — поместите его в объект data, который SDK доставляет в actionParams. Если displayType отсутствует, резолвер использует эвристику: изображение без заголовка → баннер, изображение с заголовком → с подписью, иначе классическая. Чтобы принудительно задать один макет для всей ленты из кода, установите attributes.forceCellKind.

Каждый расширенный макет деградирует корректно: если требуемая полезная нагрузка отсутствует или повреждена, карточка переключается на classic вместо пустого плейсхолдера (в лог записывается WARN).

displayTypeМакетОбязательное поле полезной нагрузкиДеградирует до
bannerИзображение на всю ширину, без текстаimage (inbox_image или data.image)classic, если нет изображения
captionedИзображение сверху, заголовок и текст нижеimage (inbox_image или data.image)classic, если нет изображения
classicЦветной аватар с инициалом + заголовок + текст
carouselГалерея из нескольких изображений со свайпомdata.carousel (массив слайдов)classic, если нет слайдов
videoПостер с значком воспроизведения, полноэкранный плеер по нажатиюdata.video (url + необязательный poster)classic, если нет дескриптора
walletКнопка «Добавить в Apple Wallet» (только iOS)data.wallet (URL .pkpass)classic, если нет URL пропуска
Карточка InboxKit типа баннер
Карточка-баннер
Карточка InboxKit с подписью
Карточка с подписью
Классическая карточка InboxKit
Классическая карточка
Карточка InboxKit типа карусель
Карточка-карусель
Видеокарточка InboxKit
Видеокарточка
Карточка InboxKit Apple Wallet
Карточка Apple Wallet

Карточки баннер, с подписью и классическая управляются стандартными полями сообщения (изображение, заголовок, текст) плюс необязательный массив buttons — см. Добавление встроенных CTA-кнопок. Карточки карусель, видео и Apple Wallet содержат дополнительные структурированные данные внутри data, описанные ниже.

Карточка-карусель

Anchor link to

Карусель отображает несколько изображений из одного сообщения — галерею со свайпом с необязательными подписями и целевыми ссылками для каждого слайда. Слайды находятся в data.carousel. Каждый слайд требует image. Поля title (подпись поверх изображения) и url (deep link при нажатии) необязательны. Слайд без изображения пропускается. Нажатие на слайд без url передаётся стандартному действию строки.

POST https://api.pushwoosh.com/json/1.3/createMessage
{
"request": {
"application": "XXXXX-XXXXX",
"auth": "API_TOKEN",
"notifications": [{
"send_date": "now",
"ios_title": "New arrivals",
"content": "Swipe through this week's drops",
"inbox_days": 7,
"data": {
"displayType": "carousel",
"carousel": [
{ "image": "https://cdn.example.com/inbox/1.jpg", "title": "New in", "url": "myapp://product/1" },
{ "image": "https://cdn.example.com/inbox/2.jpg", "title": "On sale", "url": "myapp://product/2" },
{ "image": "https://cdn.example.com/inbox/3.jpg" }
]
},
"platforms": [1]
}]
}
}

Видеокарточка

Anchor link to

Видеокарточка показывает постер с значком воспроизведения. Нажатие открывает полноэкранный плеер (со звуком, даже при включённом беззвучном режиме). Дескриптор находится в data.video: url обязателен и должен быть потоком или файлом по http/https. poster — необязательное изображение предпросмотра.

POST https://api.pushwoosh.com/json/1.3/createMessage
{
"request": {
"application": "XXXXX-XXXXX",
"auth": "API_TOKEN",
"notifications": [{
"send_date": "now",
"ios_title": "Watch the reveal",
"content": "Tap to play",
"inbox_days": 7,
"data": {
"displayType": "video",
"video": {
"url": "https://cdn.example.com/inbox/clip.mp4",
"poster": "https://cdn.example.com/inbox/poster.jpg"
}
},
"platforms": [1]
}]
}
}

Карточка Apple Wallet

Anchor link to

Карточка Apple Wallet показывает необязательное изображение, заголовок и текст над официальной кнопкой Add to Apple Wallet. Нажатие на кнопку загружает .pkpass и открывает системный лист добавления пропусков. Используйте её для доставки купонов, карт лояльности, билетов или посадочных талонов прямо из входящих. Карточка доступна только на iOS и Mac Catalyst. На других платформах сообщение отображается как классическая карточка.

URL пропуска находится в data.wallet — как строка или как объект с полем pass. Необязательный data.image добавляет изображение-герой. Кнопка скрывается автоматически, если нет URL пропуска или устройство не может добавлять пропуски.

POST https://api.pushwoosh.com/json/1.3/createMessage
{
"request": {
"application": "XXXXX-XXXXX",
"auth": "API_TOKEN",
"notifications": [{
"send_date": "now",
"ios_title": "Your loyalty card is ready",
"content": "Add it to Apple Wallet in one tap",
"inbox_days": 7,
"data": {
"displayType": "wallet",
"image": "https://cdn.example.com/inbox/loyalty.png",
"wallet": "https://passes.example.com/v1/passes/pass.com.example.loyalty/abc123?token=…"
},
"platforms": [1]
}]
}
}

Результат передаётся вашему делегату:

extension MyInboxHost: PushwooshInboxKitDelegate {
func inboxKit(_ vc: PushwooshInboxKitViewController,
didAddWalletPassFor message: PWInboxMessageProtocol) {
// Пропуск теперь в Wallet пользователя — при желании покажите подтверждение.
}
func inboxKit(_ vc: PushwooshInboxKitViewController,
didFailToAddWalletPassFor message: PWInboxMessageProtocol,
error: Error?) {
// Загрузка не удалась — покажите повтор, запишите в лог и т. д.
}
}

Оба колбэка необязательны (имеют пустые реализации по умолчанию). Если пользователь отменяет системный лист, колбэк не вызывается — это ни успех, ни ошибка.

Специальные возможности

Anchor link to

Ячейки InboxKit готовы к VoiceOver из коробки. Карточки баннер, с подписью и классическая передают заголовок, текст и дату через базовые метки. Встроенные CTA-кнопки озвучивают собственные заголовки. Расширенные карточки добавляют явную семантику:

  • Видео — постер представлен как единый элемент-кнопка с меткой «Play video» (traits .button + .startsMediaSession), поэтому VoiceOver объявляет его как медиаэлемент, а не как обычное изображение.
  • Карусель — каждый слайд является элементом-кнопкой, чья accessibility-метка — подпись слайда или «Slide», если подписи нет. Индикатор страниц объявляет текущую позицию как «n из total».
  • Apple Wallet — кнопка Add to Apple Wallet — это стандартная PKAddPassButton от Apple со своей локализованной меткой VoiceOver.

Для UI-тестирования и автоматизации заданы два стабильных accessibilityIdentifier: inboxkit.video.play на видеопостере и inboxkit.wallet.add на кнопке Wallet.

Чтение пользовательских данных из сообщения

Anchor link to

Чтобы пуш появился во входящих, запрос createMessage в Messages API должен включать inbox_image, inbox_date или inbox_days — без одного из этих полей пуш доставляется как обычное уведомление и никогда не попадает в ленту входящих. Произвольные пользовательские данные помещаются под ключ data, который SDK доставляет клиенту в качестве параметра u:

POST https://api.pushwoosh.com/json/1.3/createMessage
{
"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": {
"displayType": "captioned",
"promo_id": "SUMMER2026",
"screen": "promo_details"
},
"platforms": [1]
}]
}
}

SDK предоставляет этот объект в сообщении входящих через actionParams. Считайте его из делегата, когда пользователь нажимает на строку или встроенную CTA:

extension MyInboxHost: PushwooshInboxKitDelegate {
func inboxKit(_ vc: PushwooshInboxKitViewController,
didSelect message: PWInboxMessageProtocol) -> Bool {
guard let params = message.actionParams as? [String: Any] else { return true }
// Пользовательский объект `data` приходит под ключом "u" —
// либо как вложенный словарь, либо как строка в формате JSON,
// в зависимости от того, как была сформирована полезная нагрузка.
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 // мы обработали нажатие; SDK не должен выполнять действие по умолчанию
}
return true
}
}

Тот же поиск actionParams["u"] работает внутри inboxKit(_:didTapButton:onMessage:) для встроенных CTA-кнопок. Для типизированных случаев CTA (openURL, dismiss, markRead) SDK уже выполняет действие по умолчанию — верните true, чтобы сохранить это поведение, или false, чтобы подавить его и запустить собственную логику.

Добавление встроенных CTA-кнопок

Anchor link to

Сообщение может содержать до трёх встроенных кнопок призыва к действию (CTA). Кнопки находятся вместе с другими пользовательскими данными внутри data в виде массива buttons. SDK автоматически отображает их внутри ячеек с подписью и классических ячеек:

POST https://api.pushwoosh.com/json/1.3/createMessage
{
"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": {
"displayType": "captioned",
"promo_id": "SUMMER2026",
"buttons": [
{ "title": "Claim", "url": "https://example.com/promo/SUMMER2026" },
{ "title": "Read", "action": "markRead" },
{ "title": "Save", "action": "custom", "tag": "save_promo" }
]
},
"platforms": [1]
}]
}
}

Каждый объект кнопки имеет следующие поля:

ПолеТипКогда
titlestringОбязательно. Видимая метка кнопки.
urlstringНепустой URL, который можно разобрать, создаёт действие openURL. SDK открывает его через UIApplication.shared.open, если ваш делегат не подавляет это действие.
actionstringЯвный токен действия: dismiss (удаляет сообщение из ленты), markRead (отмечает сообщение как прочитанное) или custom (обрабатывается хостом). Регистронезависимый.
Любое другоеanyКогда action равно custom, каждый ключ в объекте кнопки, кроме title и action, пересылается вашему делегату как пользовательская полезная нагрузка — согласуйте ключ с маркетологом (например, tag) и выполняйте диспетчеризацию по нему.

Приоритет разрешения: сначала явный токен action, затем url, если он не пуст, в противном случае кнопка попадает в категорию custom, неся полную полезную нагрузку (за вычетом title и action).

Перехватывайте нажатия из вашего делегата. Свойство button.action является типизированным перечислением PushwooshInboxButtonAction:

extension MyInboxHost: PushwooshInboxKitDelegate {
func inboxKit(_ vc: PushwooshInboxKitViewController,
didTapButton button: PushwooshInboxButton,
onMessage message: PWInboxMessageProtocol) -> Bool {
switch button.action {
case .openURL(let url):
// Поведение по умолчанию подходит — пусть SDK откроет URL.
return true
case .dismiss, .markRead:
// SDK обрабатывает оба случая. Верните false, если хотите переопределить.
return true
case .custom(let payload):
// Пользовательская кнопка, определённая маркетологом. Выполняйте диспетчеризацию по согласованному ключу.
if let tag = payload["tag"] as? String {
switch tag {
case "save_promo":
saveCurrentPromoLocally(message: message)
default:
break
}
}
return true // игнорируется для custom — SDK никогда не выполняет здесь действие по умолчанию
}
}
}