Push stories para iOS
As push stories transformam uma notificação push expandida em uma experiência de stories em tela cheia, no estilo do Instagram: imagens de ponta a ponta, barras de progresso no topo, avanço automático de páginas, toque para navegar e um botão com um deep link. Elas são renderizadas por uma Notification Content Extension usando o módulo autônomo PushwooshNotificationUI — você subclasse um view controller e o SDK cuida da análise, carregamento de imagens, progresso, tempo, navegação e deep links.
Disponível desde a versão 7.0.46.

1. Adicione uma Notification Content Extension
Anchor link toNo Xcode, escolha File > New > Target…, selecione Notification Content Extension e dê um nome a ela (por exemplo, StoriesContentExtension).

2. Adicione o módulo PushwooshNotificationUI
Anchor link toPushwooshNotificationUI é um módulo autônomo sem outras dependências do Pushwoosh, então ele permanece pequeno dentro do processo da extensão. Adicione-o ao target da extensão de conteúdo (não ao target do aplicativo).
Swift Package Manager

CocoaPods
target 'StoriesContentExtension' do use_frameworks!
pod 'PushwooshXCFramework/PushwooshNotificationUI'end3. Subclasse o view controller de stories
Anchor link toSubstitua o corpo do NotificationViewController gerado por uma subclasse de PushwooshStoriesViewController. Essa é toda a integração.
import PushwooshNotificationUI
class NotificationViewController: PushwooshStoriesViewController {}4. Configure o Info.plist da extensão
Anchor link toNo Info.plist da extensão de conteúdo, defina as seguintes chaves em NSExtension > NSExtensionAttributes:
<key>UNNotificationExtensionCategory</key><string>PW_STORIES</string><key>UNNotificationExtensionUserInteractionEnabled</key><true/><key>UNNotificationExtensionDefaultContentHidden</key><true/><key>UNNotificationExtensionInitialContentSizeRatio</key><real>1.5</real>5. Envie uma notificação de push stories
Anchor link toEnvie uma notificação cuja categoria seja PW_STORIES e cujos dados personalizados contenham um bloco pw_stories. Use o campo dedicado ios_category_custom para a categoria e o campo data para o payload dos stories.
{ "request": { "application": "APPLICATION_CODE", "auth": "API_ACCESS_TOKEN", "notifications": [ { "send_date": "now", "content": "Tap to explore", "ios_title": "Push Stories", "ios_category_custom": "PW_STORIES", "ios_root_params": { "aps": { "mutable-content": 1 } }, "data": { "pw_stories": { "pages": [ { "image": "https://example.com/story-1.jpg", "duration": 5.0, "link": "yourapp://page1", "button_title": "Get started", "title": "Welcome", "subtitle": "Swipe to explore what's new" }, { "image": "https://example.com/story-2.jpg", "duration": 4.0, "link": "yourapp://page2", "button_title": "Learn more", "title": "Stay in the loop", "subtitle": "Updates, tips and more" } ] } } } ] }}Cada página suporta os seguintes campos. Apenas image é obrigatório; os demais são opcionais.
| Campo | Descrição |
|---|---|
image | URL da imagem em tela cheia para a página. |
duration | Segundos que a página permanece na tela antes de avançar automaticamente. O padrão é cerca de 5 segundos. |
link | Deep link aberto quando o botão da página é tocado. |
button_title | Título do botão da página. |
title | Texto do título sobreposto na página. |
subtitle | Texto do subtítulo sobreposto na página. |
Personalização
Anchor link toSobrescreva propriedades em sua subclasse para ajustar a experiência. Todas têm padrões sensatos.
import PushwooshNotificationUI
class NotificationViewController: PushwooshStoriesViewController { override var storyAspectRatio: CGFloat { 1.5 } // keep in sync with InitialContentSizeRatio override var hapticsEnabled: Bool { true } override var longPressToPauseEnabled: Bool { true } override var crossfadesBetweenPages: Bool { true } override var loopsAfterLastPage: Bool { false }}| Propriedade | Padrão | Descrição |
|---|---|---|
storyAspectRatio | 1.5 | Proporção (altura ÷ largura) da área dos stories. Mantenha-a em sincronia com UNNotificationExtensionInitialContentSizeRatio. |
hapticsEnabled | false | Reproduz um leve toque tátil na navegação por zona de toque. |
longPressToPauseEnabled | false | Pressionar e segurar pausa a página atual; soltar retoma. |
crossfadesBetweenPages | false | Transição suave (cross-dissolve) entre as páginas em vez de um corte seco. Recorre a uma mudança instantânea quando a opção Reduzir Movimento está ativada. |
loopsAfterLastPage | false | Reinicia a partir da primeira página após a última terminar. |
appGroupIdentifier | nil | App Group compartilhado com uma Notification Service Extension para pré-cache de mídia (veja abaixo). |
Você também pode sobrescrever showDefaultContent(for:) para personalizar o conteúdo de fallback exibido quando o payload está ausente ou malformado (por padrão, ele mostra o corpo do alerta).
Pré-cache de mídia
Anchor link toPara um primeiro quadro instantâneo e offline, compartilhe um App Group entre sua Content Extension e uma Notification Service Extension. Sobrescreva appGroupIdentifier no controller de stories e, em seguida, pré-baixe a mídia a partir do didReceive(_:withContentHandler:) da sua Service Extension:
import PushwooshNotificationUI
PushwooshStoriesMediaPrefetcher.prefetch( userInfo: request.content.userInfo, appGroupIdentifier: "group.com.example.app") { contentHandler(bestAttemptContent)}Habilite a capacidade App Groups em ambas as extensões com o mesmo identificador de grupo e envie mutable-content: 1 para que a Service Extension seja executada. Sem um App Group, a mídia é armazenada em cache no diretório tmp da extensão.
Callbacks de ciclo de vida e análise
Anchor link toDefina storiesDelegate para observar eventos de stories — impressões de página, toques em botões, conclusão e fallback. Conforme-se com PushwooshStoriesDelegate; cada método é opcional, então implemente apenas os que você precisa.
import PushwooshNotificationUI
class NotificationViewController: PushwooshStoriesViewController, PushwooshStoriesDelegate { override func viewDidLoad() { super.viewDidLoad() storiesDelegate = self }
func storiesViewController(_ controller: PushwooshStoriesViewController, didStartWithPageCount pageCount: Int) {} func storiesViewController(_ controller: PushwooshStoriesViewController, didShow page: StoryPage, at index: Int) {} func storiesViewController(_ controller: PushwooshStoriesViewController, didTapActionFor page: StoryPage, at index: Int) {} func storiesViewControllerDidFinish(_ controller: PushwooshStoriesViewController) {} func storiesViewControllerDidShowFallback(_ controller: PushwooshStoriesViewController) {}}| Callback | Quando é acionado |
|---|---|
didStartWithPageCount: | Um payload de stories válido foi analisado e a reprodução está prestes a começar. |
didShow:at: | Uma página tornou-se visível. Use-o para impressões por página. |
didTapActionFor:at: | O usuário tocou no botão de chamada para ação. |
storiesViewControllerDidFinish: | A última página terminou de ser reproduzida. |
storiesViewControllerDidShowFallback: | O payload estava ausente ou malformado e o conteúdo de fallback foi exibido. |
O StoryPage passado para os callbacks expõe os imageURL, duration, link, buttonTitle, title e subtitle da página.
Navegação
Anchor link toToque no terço direito da tela para ir para a próxima página e no terço esquerdo para voltar. O deslize horizontal não é usado intencionalmente, pois entra em conflito com o gesto do sistema para dispensar notificações. Tocar no botão da página abre seu deep link e dispensa a notificação.