Получение флоу и пейволов — iOS

What getFlow retrieves
Flows BETA Built in Flow builder — renders natively on device, no WebView
Paywall Builder paywalls All existing Paywall Builder content

После того как вы разработали флоу или пейвол в Paywall Builder, можно показывать его в мобильном приложении. Первый шаг — получить флоу или пейвол, связанный с плейсментом, и его конфигурацию отображения, как описано ниже.

Хотите увидеть реальный пример интеграции Adapty SDK в мобильное приложение? Ознакомьтесь с нашими примерами приложений — они демонстрируют полную настройку: отображение пейволов, совершение покупок и другие базовые функции.

Перед началом работы
  1. Создайте продукты в дашборде Adapty.
  2. Создайте флоу/пейвол и добавьте в него продукты в дашборде Adapty.
  3. Создайте плейсменты и добавьте в них флоу/пейвол в дашборде Adapty.
  4. Установите SDK Adapty в своё мобильное приложение.

Получение флоу/пейвола

Если вы создали флоу или пейвол с помощью Flow Builder или Paywall Builder, вам не нужно беспокоиться о том, как его отрендерить в коде мобильного приложения. Такой флоу или пейвол уже содержит всё необходимое: что показывать и как показывать. Тем не менее вам нужно получить его ID через плейсмент, загрузить конфигурацию отображения и затем показать его в мобильном приложении. Чтобы обеспечить оптимальную производительность, важно получать флоу или пейвол и его конфигурацию отображения как можно раньше — так у изображений будет достаточно времени для загрузки до показа пользователю.

Для получения флоу или пейвола используйте метод getFlow:

Параметры:

ПараметрНаличиеОписание
placementIdобязательныйИдентификатор нужного плейсмента. Это значение вы указали при создании плейсмента в дашборде Adapty.
fetchPolicyпо умолчанию: .reloadRevalidatingCacheData

По умолчанию SDK пытается загрузить данные с сервера и возвращает кешированные данные в случае сбоя. Мы рекомендуем этот вариант, поскольку он гарантирует, что пользователи всегда получают самые актуальные данные.

Однако если у ваших пользователей нестабильный интернет, рассмотрите использование .returnCacheDataElseLoad — оно возвращает кешированные данные, если они есть. В этом случае пользователи могут не получить самые последние данные, но загрузка будет быстрее независимо от качества соединения. Кеш регулярно обновляется, поэтому его безопасно использовать в течение сессии, чтобы избежать лишних сетевых запросов.

Обратите внимание: кеш сохраняется при перезапуске приложения и очищается только при переустановке или вручную.

Adapty SDK хранит пейволы локально на двух уровнях: регулярно обновляемый кеш, описанный выше, и резервные пейволы. Мы также используем CDN для более быстрой загрузки пейволов и отдельный резервный сервер на случай недоступности CDN. Система разработана так, чтобы вы всегда получали актуальную версию пейволов, даже при нестабильном интернете.

loadTimeoutпо умолчанию: 5 сек

Это значение ограничивает таймаут метода. Если таймаут истёк, будут возвращены кешированные данные или локальный резервный пейвол.

Обратите внимание: в редких случаях метод может завершиться с небольшой задержкой относительно значения, указанного в loadTimeout, поскольку операция может состоять из нескольких внутренних запросов.

Параметры ответа:
ПараметрОписание
FlowОбъект AdaptyFlow, содержащий плейсмент, идентификаторы (id, variationId), имя, Remote Config и флаг hasViewConfiguration, указывающий, включает ли флоу конфигурацию представления. Чтобы получить продукты для предзагрузки, кастомного UI или программных проверок, вызовите getPaywallProducts(flow:).

Получение конфигурации представления

После получения флоу или пейвола проверьте, включает ли он конфигурацию представления, с помощью flow.hasViewConfiguration. Этот флаг показывает, как был создан плейсмент в дашборде Adapty:

  • true — плейсмент создан во Flow Builder (флоу) или Paywall Builder (пейвол). Adapty отрисовывает интерфейс за вас. Продолжайте выполнять шаги ниже, чтобы получить конфигурацию представления и показать флоу или пейвол.
  • false — плейсмент является кастомным пейволом без интерфейса Builder. Используйте метод getFlowConfiguration, чтобы загрузить конфигурацию представления.

guard flow.hasViewConfiguration else {
    // handle as remote config paywall
    return
}

let flowConfiguration = try await AdaptyUI.getFlowConfiguration(forFlow: flow)

Параметры:

ПараметрНаличиеОписание
forFlowобязательныйОбъект AdaptyFlow, полученный через Adapty.getFlow.
locale

необязательный

по умолчанию: nil

Идентификатор локализации пейвола. Ожидается в виде языкового кода с одним или двумя подтегами, разделёнными - (например, en, pt-br). См. Локализации и коды локалей.
loadTimeoutпо умолчанию: 5 секОграничивает тайм-аут для этого метода. Если тайм-аут истекает, возвращаются кэшированные данные или локальный резервный пейвол. Обратите внимание, что в редких случаях метод может завершиться чуть позже указанного в loadTimeout значения, поскольку операция может включать несколько запросов.
productsнеобязательныйПередайте массив объектов AdaptyPaywallProduct, чтобы оптимизировать время отображения продуктов на экране. Если передать nil, AdaptyUI автоматически загрузит необходимые продукты.
systemRequestsHandlerнеобязательныйОбъект, реализующий AdaptySystemRequestsHandler, который обрабатывает запросы системных разрешений и запросы на отзыв, инициированные действиями флоу. Требуется только если ваш флоу включает такие действия.
assetsResolverнеобязательныйСловарь [String: AdaptyCustomAsset], переопределяющий изображения и видео во флоу/пейволе. См. Настройка ресурсов.
timerResolverнеобязательныйОбъект, реализующий AdaptyTimerResolver, который предоставляет даты окончания для таймеров, определённых разработчиком. См. Настройка таймеров разработчика.
После загрузки отобразите флоу/пейвол.

Получите флоу или пейвол для аудитории по умолчанию, чтобы ускорить загрузку

Как правило, флоу и пейволы загружаются почти мгновенно, поэтому беспокоиться об ускорении этого процесса не нужно. Однако если у вас много аудиторий и плейсментов, а пользователи работают с медленным интернетом, загрузка флоу или пейвола может занять больше времени, чем хотелось бы. В таких ситуациях имеет смысл показывать флоу или пейвол по умолчанию — это обеспечит плавный пользовательский опыт вместо пустого экрана. Чтобы решить эту проблему, используйте метод getFlowForDefaultAudience, который получает флоу или пейвол указанного плейсмента для аудитории All Users. Однако важно понимать, что рекомендуемый подход — получать флоу или пейвол через метод getFlow, как описано в разделе Получение информации о пейволе выше.

Почему мы рекомендуем использовать getFlow

Метод getFlowForDefaultAudience имеет ряд существенных недостатков:

  • Потенциальные проблемы обратной совместимости: если нужно показывать разные пейволы для разных версий приложения (текущей и будущих), могут возникнуть сложности. Придётся либо проектировать пейволы с учётом текущей (устаревшей) версии, либо смириться с тем, что пользователи на ней могут столкнуться с нерендерящимися пейволами.
  • Потеря таргетинга: все пользователи будут видеть один и тот же пейвол, настроенный для аудитории All Users, — а значит, вы теряете персонализированный таргетинг (в том числе по странам, маркетинговой атрибуции или собственным кастомным атрибутам). Если вы готовы принять эти ограничения ради более быстрой загрузки флоу или пейвола, используйте метод getFlowForDefaultAudience следующим образом. В противном случае используйте getFlow, описанный выше.
Adapty.getFlowForDefaultAudience(placementId: "YOUR_PLACEMENT_ID") { result in
    switch result {
        case let .success(flow):
            // the requested flow
        case let .failure(error):
            // handle the error
    }
}
ПараметрОбязательностьОписание
placementIdобязательныйИдентификатор плейсмента. Это значение вы указали при создании плейсмента в дашборде Adapty.
fetchPolicyпо умолчанию: .reloadRevalidatingCacheData

По умолчанию SDK пытается загрузить данные с сервера, а в случае ошибки возвращает кешированные данные. Мы рекомендуем этот вариант, так как он гарантирует, что пользователи всегда получают актуальные данные.

Однако если у ваших пользователей нестабильное интернет-соединение, рассмотрите вариант .returnCacheDataElseLoad: он возвращает кешированные данные, если они есть. В этом случае пользователи могут не получить самые свежие данные, зато загрузка будет быстрее вне зависимости от качества соединения. Кеш регулярно обновляется, поэтому использовать его в течение сессии для снижения количества сетевых запросов безопасно.

Обратите внимание: кеш сохраняется после перезапуска приложения и очищается только при его переустановке или принудительной очистке вручную.

Настройка ресурсов

Чтобы кастомизировать изображения и видео в пейволе или флоу, используйте пользовательские ресурсы.

Для hero-изображений и видео есть предопределённые идентификаторы: hero_image и hero_video. В пакете пользовательских ресурсов вы обращаетесь к этим элементам по их идентификаторам и задаёте нужное поведение.

Для остальных изображений и видео необходимо задать пользовательский идентификатор в дашборде Adapty.

Например, вы можете:

  • Показывать разные изображения или видео разным пользователям.
  • Показывать локальное превью, пока загружается основное изображение с сервера.
  • Показывать превью перед воспроизведением видео.
  • Указать разрешение видео в пикселях, чтобы плеер заранее зарезервировал место в макете (соотношение сторон = width / height) до загрузки видео. Передайте nil, чтобы пропустить этот параметр.

Вот пример того, как передавать пользовательские ресурсы через простой словарь:

let customAssets: [String: AdaptyCustomAsset] = [
    // Show a local image using a custom ID
    "custom_image": .image(
        .uiImage(value: UIImage(named: "image_name")!)
    ),

    // Show a local preview image while a remote main image is loading
    "hero_image": .image(
        .remote(
            url: URL(string: "https://example.com/image.jpg")!,
            preview: UIImage(named: "preview_image")
        )
    ),

    // Show a local video with a preview image and a known resolution
    "hero_video": .video(
        .file(
            url: Bundle.main.url(forResource: "custom_video", withExtension: "mp4")!,
            preview: .uiImage(value: UIImage(named: "video_preview")!),
            resolution: CGSize(width: 1080, height: 1920)
        )
    ),
]

let flowConfig = try await AdaptyUI.getFlowConfiguration(
    forFlow: flow,
    assetsResolver: customAssets
)

Если ресурс не найден, пейвол/флоу отобразится с внешним видом по умолчанию.

Настройка таймеров, заданных разработчиком

Чтобы использовать пользовательские таймеры в мобильном приложении, создайте объект, реализующий протокол AdaptyTimerResolver. Этот объект определяет, как должен отображаться каждый таймер. Если хотите, можно напрямую использовать словарь [String: Date] — он уже соответствует этому протоколу. Пример:

@MainActor
struct AdaptyTimerResolverImpl: AdaptyTimerResolver {
    func timerEndAtDate(for timerId: String) -> Date {
        switch timerId {
        case "CUSTOM_TIMER_6H":
            Date(timeIntervalSinceNow: 3600.0 * 6.0) // 6 hours
        case "CUSTOM_TIMER_NY":
            Calendar.current.date(from: DateComponents(year: 2025, month: 1, day: 1)) ?? Date(timeIntervalSinceNow: 3600.0)
        default:
            Date(timeIntervalSinceNow: 3600.0) // 1 hour
        }
    }
}

В этом примере CUSTOM_TIMER_NY и CUSTOM_TIMER_6H — это Timer ID пользовательских таймеров, заданных вами в дашборде Adapty. timerResolver гарантирует, что приложение динамически обновляет каждый таймер правильным значением. Например:

  • CUSTOM_TIMER_NY: время, оставшееся до окончания таймера, например до Нового года.
  • CUSTOM_TIMER_6H: время, оставшееся в 6-часовом периоде, который начался, когда пользователь открыл пейвол.

После того как вы создали визуальную часть пейвола с помощью Paywall Builder в дашборде Adapty, вы можете отобразить его в своём мобильном приложении. Первый шаг — получить пейвол, связанный с плейсментом, и его конфигурацию отображения, как описано ниже.

Обратите внимание, что эта тема относится к пейволам, настроенным с помощью Paywall Builder. Если вы реализуете пейволы вручную, обратитесь к разделу Получение пейволов и продуктов для пейволов с Remote Config.

Прежде чем начать показывать пейволы в своём мобильном приложении, ознакомьтесь с реальным примером интеграции Adapty SDK — загляните в наши примеры приложений, где показана полная настройка: отображение пейволов, совершение покупок и другие базовые функции.

Прежде чем начать показывать пейволы в мобильном приложении
  1. Создайте продукты в дашборде Adapty.
  2. Создайте пейвол и добавьте в него продукты в дашборде Adapty.
  3. Создайте плейсменты и добавьте в них пейвол в дашборде Adapty.
  4. Установите SDK Adapty в своём мобильном приложении.

Получение пейвола, созданного в Paywall Builder

Если вы создали пейвол с помощью Paywall Builder, вам не нужно беспокоиться о его отрисовке в коде мобильного приложения для показа пользователю. Такой пейвол содержит как то, что должно отображаться, так и то, как именно это должно выглядеть. Тем не менее вам нужно получить его ID через плейсмент, конфигурацию отображения, а затем показать пейвол в приложении. Чтобы обеспечить оптимальную производительность, важно получать пейвол и его конфигурацию отображения как можно раньше — это даёт достаточно времени для загрузки изображений до того, как пользователь увидит экран.

Чтобы получить пейвол, используйте метод getPaywall:

Параметры:

ПараметрНаличиеОписание
placementIdобязательныйИдентификатор нужного плейсмента. Это значение вы указали при создании плейсмента в дашборде Adapty.
locale

необязательный

по умолчанию: en

Идентификатор локализации пейвола. Ожидается в виде языкового кода из одного или двух подтегов, разделённых символом минус (-). Первый подтег — язык, второй — регион.

Например: en означает английский, pt-br — бразильский португальский.

Подробнее о кодах локалей и рекомендациях по их использованию см. в разделе Локализации и коды локалей.

fetchPolicyпо умолчанию: .reloadRevalidatingCacheData

По умолчанию SDK пытается загрузить данные с сервера и возвращает кешированные данные в случае сбоя. Мы рекомендуем этот вариант, так как он гарантирует, что пользователи всегда получают самые актуальные данные.

Однако если у ваших пользователей нестабильное интернет-соединение, рассмотрите использование .returnCacheDataElseLoad — оно возвращает кешированные данные при их наличии. В этом случае пользователи могут получить не самые последние данные, зато время загрузки будет минимальным вне зависимости от качества соединения. Кеш регулярно обновляется, поэтому его безопасно использовать в течение сессии, чтобы избежать лишних сетевых запросов.

Обратите внимание: кеш сохраняется при перезапуске приложения и очищается только при его переустановке или вручную.

Adapty SDK хранит пейволы локально на двух уровнях: регулярно обновляемый кеш, описанный выше, и резервные пейволы. Для ускорения загрузки пейволов мы также используем CDN и отдельный резервный сервер на случай недоступности CDN. Эта система обеспечивает получение актуальной версии пейволов и надёжную работу даже при слабом интернет-соединении.

loadTimeoutпо умолчанию: 5 сек

Ограничивает тайм-аут этого метода. По истечении тайм-аута возвращаются кешированные данные или локальный резервный пейвол.

Обратите внимание: в редких случаях метод может завершиться с небольшой задержкой относительно значения loadTimeout, поскольку операция может включать несколько запросов внутри.

ПараметрОписание
:--------:----------
PaywallОбъект AdaptyPaywall со списком идентификаторов продуктов, идентификатором пейвола, Remote Config и другими свойствами.

Получение конфигурации представления для пейвола, созданного в Paywall Builder

Убедитесь, что в Paywall Builder включён переключатель Show on device. Если он выключен, конфигурация представления не будет доступна для получения.

После получения пейвола проверьте, содержит ли он конфигурацию представления — это означает, что пейвол был создан с помощью Paywall Builder. Наличие или отсутствие конфигурации определяет способ отображения пейвола. Если конфигурация представления есть — работайте с ним как с пейволом Paywall Builder; если нет — обработайте его как пейвол с Remote Config. Используйте метод getPaywallConfiguration для загрузки конфигурации представления.


guard paywall.hasViewConfiguration else {
    //  use your custom logic
    return
}

do {
    let paywallConfiguration = try await AdaptyUI.getPaywallConfiguration(
            forPaywall: paywall,
            products: products
    )
    // use loaded configuration
} catch {
    // handle the error
}

Параметры:

ПараметрНаличиеОписание
paywallобязательныйОбъект AdaptyPaywall для получения контроллера нужного пейвола.
loadTimeoutпо умолчанию: 5 секОграничивает таймаут для этого метода. Если таймаут истекает, возвращаются кэшированные данные или локальный резервный вариант. В редких случаях метод может завершиться чуть позже указанного значения loadTimeout, поскольку операция может включать несколько запросов под капотом.
productsнеобязательныйПередайте массив объектов AdaptyPaywallProduct, чтобы оптимизировать время отображения продуктов на экране. Если передано nil, AdaptyUI автоматически получит необходимые продукты.

Если вы используете несколько языков, узнайте, как добавить локализацию Paywall Builder и как правильно использовать коды локалей здесь.

После загрузки отобразите пейвол.

Получение пейвола для аудитории по умолчанию ради более быстрой загрузки

Как правило, пейволы загружаются практически мгновенно, поэтому беспокоиться об ускорении этого процесса не нужно. Однако если у вас много аудиторий и пейволов, а пользователи работают с медленным интернетом, загрузка пейвола может занять больше времени, чем хотелось бы. В таких ситуациях имеет смысл показывать пейвол по умолчанию — это обеспечит плавный пользовательский опыт вместо того, чтобы не показывать пейвол вовсе. Чтобы решить эту задачу, используйте метод getPaywallForDefaultAudience, который получает пейвол указанного плейсмента для аудитории All Users. Однако важно понимать, что рекомендуемый подход — получать пейвол методом getPaywall, как описано в разделе Получение информации о пейволе выше.

Почему мы рекомендуем использовать getPaywall

Метод getPaywallForDefaultAudience имеет ряд существенных недостатков:

  • Возможные проблемы с обратной совместимостью: если нужно показывать разные пейволы для разных версий приложения (текущей и будущих), могут возникнуть сложности. Придётся либо проектировать пейволы с поддержкой текущей (устаревшей) версии, либо смириться с тем, что у пользователей на старой версии пейволы могут не отображаться корректно.
  • Потеря таргетинга: все пользователи будут видеть один и тот же пейвол, настроенный для аудитории All Users, — это означает отказ от персонализированного таргетинга (в том числе по странам, маркетинговой атрибуции или собственным пользовательским атрибутам). Если вы готовы принять эти компромиссы ради более быстрой загрузки пейвола, используйте метод getPaywallForDefaultAudience следующим образом. В противном случае используйте getPaywall, описанный выше.
Adapty.getPaywallForDefaultAudience(placementId: "YOUR_PLACEMENT_ID", locale: "en") { result in
    switch result {
        case let .success(paywall):
            // the requested paywall
        case let .failure(error):
            // handle the error
    }
}

Метод getPaywallForDefaultAudience доступен начиная с версии iOS SDK 2.11.2.

ПараметрНаличиеОписание
placementIdобязательныйИдентификатор плейсмента. Это значение, которое вы указали при создании плейсмента в дашборде Adapty.
locale

необязательный

по умолчанию: en

Идентификатор локализации пейвола. Ожидается, что этот параметр будет языковым кодом, состоящим из одного или нескольких подтегов, разделённых символом минус (-). Первый подтег обозначает язык, второй — регион.

Например: en означает английский, pt-br — бразильский португальский.

Подробнее о кодах локалей и рекомендациях по их использованию см. в разделе Локализации и коды локалей.

fetchPolicyпо умолчанию: .reloadRevalidatingCacheData

По умолчанию SDK пытается загрузить данные с сервера и возвращает кэшированные данные в случае неудачи. Мы рекомендуем этот вариант, поскольку он гарантирует, что пользователи всегда получают актуальные данные.

Однако если у ваших пользователей нестабильное интернет-соединение, рассмотрите использование .returnCacheDataElseLoad для возврата кэшированных данных при их наличии. В этом случае пользователи могут получать не самые свежие данные, зато время загрузки будет меньше вне зависимости от качества соединения. Кэш регулярно обновляется, поэтому его безопасно использовать в течение сессии, чтобы избежать лишних сетевых запросов.

Обратите внимание, что кэш сохраняется при перезапуске приложения и очищается только при его переустановке или вручную.

Настройка ресурсов

Чтобы кастомизировать изображения и видео в пейволе, используйте кастомные ресурсы.

Для hero-изображений и видео есть предустановленные ID: hero_image и hero_video. В бандле кастомных ресурсов вы обращаетесь к этим элементам по их ID и меняете их поведение.

Для остальных изображений и видео нужно задать кастомный ID в дашборде Adapty.

Например, можно:

  • Показывать одним пользователям одно изображение или видео, другим — другое.
  • Показывать локальное превью, пока загружается основное изображение с сервера.
  • Показывать превью перед воспроизведением видео.

Чтобы использовать эту функцию, обновите Adapty iOS SDK до версии 3.7.0 или выше.

Вот пример того, как можно передать пользовательские ресурсы через простой словарь:

let customAssets: [String: AdaptyCustomAsset] = [
    // Показать локальное изображение с пользовательским ID
    "custom_image": .image(
        .uiImage(value: UIImage(named: "image_name")!)
    ),

    // Показать локальное превью, пока загружается основное изображение
    "hero_image": .image(
        .remote(
            url: URL(string: "https://example.com/image.jpg")!,
            preview: UIImage(named: "preview_image")
        )
    ),

    // Показать локальное видео с превью-изображением
    "hero_video": .video(
        .file(
            url: Bundle.main.url(forResource: "custom_video", withExtension: "mp4")!,
            preview: .uiImage(value: UIImage(named: "video_preview")!)
        )
    ),
]

let paywallConfig = try await AdaptyUI.getPaywallConfiguration(
    forPaywall: paywall,
    assetsResolver: customAssets
)

Если ресурс не найден, пейвол вернётся к своему виду по умолчанию.

Настройка таймеров, определённых разработчиком

Чтобы использовать пользовательские таймеры в мобильном приложении, создайте объект, реализующий протокол AdaptyTimerResolver. Этот объект определяет, как должен отображаться каждый таймер. Если хотите, можно напрямую использовать словарь [String: Date] — он уже соответствует этому протоколу. Пример:

@MainActor
struct AdaptyTimerResolverImpl: AdaptyTimerResolver {
    func timerEndAtDate(for timerId: String) -> Date {
        switch timerId {
        case "CUSTOM_TIMER_6H":
            Date(timeIntervalSinceNow: 3600.0 * 6.0) // 6 часов
        case "CUSTOM_TIMER_NY":
            Calendar.current.date(from: DateComponents(year: 2025, month: 1, day: 1)) ?? Date(timeIntervalSinceNow: 3600.0)
        default:
            Date(timeIntervalSinceNow: 3600.0) // 1 час
        }
    }
}

В этом примере CUSTOM_TIMER_NY и CUSTOM_TIMER_6H — это Timer ID таймеров, заданных разработчиком в дашборде Adapty. timerResolver гарантирует, что приложение динамически обновляет каждый таймер нужным значением. Например:

  • CUSTOM_TIMER_NY: время, оставшееся до окончания таймера, например до Нового года.
  • CUSTOM_TIMER_6H: время, оставшееся в 6-часовом периоде, который начался, когда пользователь открыл пейвол.