Оптимизация загрузки пейвола в iOS SDK

Надёжная загрузка пейвола на iOS решает три задачи: быстрый рендеринг, возврат пейвола с нужной аудиторией и корректный фолбэк при медленной сети. Правила ниже охватывают тайминг, кэширование и резервные сценарии.

Tip

Правила предполагают, что Adapty.activate() и Adapty.identify() уже завершились. См. Порядок вызовов в iOS SDK.

Правила и подводные камни

Делайте этоНе делайте этоПочему
Загружайте плейсмент перед показом или прогревайте кэш с помощью preloadFlows (SDK 4.1+).Не запускайте свои параллельные вызовы getFlow при старте приложения.Самодельный burst-префетч блокирует главный поток и вызывает чёрный экран. preloadFlows создан для этого и использует единый таймаут для всего пакета.
Вызывайте getPaywall после того, как атрибуция успела разрешиться — например, через 1–2 секунды после activate или после срабатывания onProfileUpdate.Не вызывайте getPaywall в App.init().Атрибуция ещё не поступила. Пейвол разрешается по дефолтной аудитории и молча обходит сегменты и персонализацию ASA.
Задайте loadTimeout и настройте резервный пейвол для каждого плейсмента.Не ждите ответа getPaywall бесконечно.Без таймаута пользователи с плохим соединением видят пустой экран до тех пор, пока сеть не ответит, — или закрывают приложение.

Подробнее о параметрах fetchPolicy и loadTimeout — в разделе Получение пейволов и продуктов, о выборе подходящего плейсмента — в разделе Плейсменты.

Предзагрузка плейсментов

Info

Эти методы доступны начиная с версии SDK 4.1.

preloadFlows и preloadOnboardings заранее загружают плейсменты в кэш SDK. Последующий вызов getFlow или getOnboarding для того же плейсмента разрешается из кэша, а не из сети — пейвол отображается без видимой задержки.

Используйте их, когда вы заранее знаете, какие плейсменты понадобятся в текущей сессии, но не хотите показывать их прямо сейчас — например, сразу после завершения activate и identify, для пейвола за кнопкой, которую пользователь ещё не нажал.

Параметры:

  • placementIds (обязательный): плейсменты для предзагрузки. Пустые и дублирующиеся идентификаторы игнорируются.
  • locale (необязательный, только для preloadOnboardings): локаль онбординга для кэширования.
  • loadTimeout (необязательный): таймаут в секундах для всего пакета, а не для отдельного плейсмента. По умолчанию — 5 секунд; значения ниже 1 секунды округляются до 1 секунды.

Важные особенности поведения:

  • Методы выбрасывают исключение только после попытки обработать все плейсменты, а ошибка агрегирует сбои по каждому из них. Сбой в одном плейсменте не останавливает остальные.
  • Если плейсмент завершается таймаутом или сетевой ошибкой, SDK откатывается к варианту для аудитории по умолчанию для этого плейсмента. Остальные сбои сообщаются как есть.
  • Если таймаут срабатывает до завершения запроса с таргетингом по аудитории, SDK всё равно пытается получить вариант для аудитории по умолчанию в рамках оставшегося бюджета.
  • Предзагрузка только прогревает кэш. Она не возвращает контент — для отображения по-прежнему нужно вызывать getFlow или getOnboarding.

Определите, какой плейсмент не загрузился

Выброшенная ошибка — это один объект AdaptyError, охватывающий весь пакет, с кодом networkFailed (2002). Чтобы увидеть отдельные сбои, обратитесь к свойству preloadErrors — словарю с ключами по идентификаторам плейсментов:

do {
    try await Adapty.preloadFlows(placementIds: ["onboarding", "main_paywall"])
} catch {
    for (placementId, placementError) in error.preloadErrors ?? [:] {
        // log or retry the individual placement
    }
}

preloadErrors равен nil для любой ошибки, которая не возникла в результате вызова preload, поэтому значение nil означает «не ошибка предзагрузки», а не «ошибок нет».

Чтобы прогреть кэш без ожидания сегментации аудитории, используйте варианты для аудитории по умолчанию:

try await Adapty.preloadFlowsForDefaultAudience(placementIds: ["main_paywall"])
try await Adapty.preloadOnboardingsForDefaultAudience(placementIds: ["intro"])

Настройка для слабого соединения

Для рынков с постоянно плохим интернетом (сельская местность, транспорт, регионы с проблемами маршрутизации):

  • Используйте fetchPolicy: .returnCacheDataElseLoad для всех запросов, кроме самого первого.
  • Настройте резервный пейвол для каждого плейсмента в дашборде Adapty.
  • Установите loadTimeout в диапазоне 3–5 секунд и принимайте резервный пейвол при срабатывании таймаута.
  • Не блокируйте отображение пейвола вызовом getProfile(). Вызывайте getPaywall независимо, чтобы медленный профиль не задерживал интерфейс.