---
title: "Получение пейволов Paywall Builder и их конфигурации в iOS SDK"
description: "Узнайте, как получать PB-пейволы в Adapty для управления подписками в вашем iOS-приложении."
---

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

:::warning
Новый Paywall Builder работает с iOS SDK версии 3.0 и выше. Информацию об отображении пейволов, созданных с помощью устаревшего Paywall Builder в Adapty SDK v2, см. в разделе [Отображение пейволов, созданных с помощью устаревшего Paywall Builder](adapty-paywall-builder).
:::

Обратите внимание, что этот раздел относится к пейволам, настроенным в Paywall Builder. Если вы реализуете пейволы вручную, обратитесь к разделу [Получение пейволов и продуктов для Remote Config пейволов в мобильном приложении](fetch-paywalls-and-products).

:::tip

Хотите увидеть реальный пример интеграции Adapty SDK в мобильное приложение? Посмотрите наши [примеры приложений](sample-apps) — они демонстрируют полную настройку: отображение пейволов, совершение покупок и другие базовые функции.

:::

<details>
   <summary>Перед началом отображения пейволов в мобильном приложении (нажмите, чтобы развернуть)</summary>

1. [Создайте продукты](create-product) в дашборде Adapty.
2. [Создайте пейвол и добавьте в него продукты](create-paywall) в дашборде Adapty.
3. [Создайте плейсменты и добавьте в них пейвол](create-placement) в дашборде Adapty.
4. Установите [Adapty SDK](sdk-installation-ios) в мобильное приложение.
</details>

## Получение пейвола, созданного в Paywall Builder \{#fetch-paywall-designed-with-paywall-builder\}

Если вы [создали пейвол с помощью Paywall Builder](adapty-paywall-builder), вам не нужно самостоятельно реализовывать его отрисовку в коде мобильного приложения. Такой пейвол содержит и то, что должно отображаться, и то, как именно это должно выглядеть. Тем не менее вам нужно получить его ID через плейсмент, конфигурацию отображения, а затем показать его в приложении.

Для обеспечения оптимальной производительности важно получить пейвол и его [конфигурацию отображения](get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) как можно раньше, чтобы изображения успели загрузиться до момента показа пользователю.

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

<Tabs>
<TabItem value="swift" label="Swift">
```swift showLineNumbers
do {
    let paywall = try await Adapty.getPaywall("YOUR_PLACEMENT_ID")
    // the requested paywall
} catch {
    // handle the error
}
```
</TabItem>
<TabItem value="callback" label="Swift-Callback">

```swift showLineNumbers
Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en") { result in
    switch result {
        case let .success(paywall):
            // the requested paywall
        case let .failure(error):
            // handle the error
    }
}
```
</TabItem>
</Tabs>

Параметры:

| Параметр | Наличие | Описание |
|---------|--------|-----------|
| **placementId** | обязательный | Идентификатор нужного [плейсмента](placements). Это значение вы указали при создании плейсмента в дашборде Adapty. |
| **locale** | <p>опциональный</p><p>по умолчанию: `en`</p> | <p>Идентификатор [локализации пейвола](add-paywall-locale-in-adapty-paywall-builder). Ожидается языковой код, состоящий из одного или двух субтегов, разделённых символом минуса (**-**). Первый субтег — язык, второй — регион.</p><p></p><p>Пример: `en` — английский, `pt-br` — бразильский португальский.</p><p>Подробнее о кодах локалей и рекомендациях по их использованию см. в разделе [Локализации и коды локалей](localizations-and-locale-codes).</p> |
| **fetchPolicy** | по умолчанию: `.reloadRevalidatingCacheData` | <p>По умолчанию SDK пытается загрузить данные с сервера и возвращает кэшированные данные в случае неудачи. Мы рекомендуем этот вариант, поскольку он гарантирует, что пользователи всегда получают актуальные данные.</p><p></p><p>Однако если у ваших пользователей нестабильное интернет-соединение, рассмотрите использование `.returnCacheDataElseLoad` для возврата кэшированных данных при их наличии. В этом случае пользователи могут получить не самые последние данные, но загрузка будет быстрее вне зависимости от качества соединения. Кэш регулярно обновляется, поэтому его безопасно использовать в течение сессии во избежание лишних сетевых запросов.</p><p></p><p>Кэш сохраняется при перезапуске приложения и очищается только при его переустановке или ручной очистке.</p><p></p><p>Adapty SDK хранит пейволы локально в двух слоях: регулярно обновляемый кэш, описанный выше, и [резервные пейволы](fallback-paywalls). Также используется CDN для ускорения загрузки и отдельный резервный сервер на случай недоступности CDN. Система гарантирует получение актуальных версий пейволов и надёжную работу даже при слабом интернет-соединении.</p> |
| **loadTimeout** | по умолчанию: 5 сек | <p>Ограничивает время ожидания для этого метода. По истечении таймаута возвращаются кэшированные данные или локальный резервный вариант.</p><p>Обратите внимание, что в редких случаях таймаут метода может наступить чуть позже указанного в `loadTimeout`, поскольку операция может состоять из нескольких запросов.</p> |

Параметры ответа:

| Параметр | Описание |
| :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Paywall   | Объект [`AdaptyPaywall`](https://swift.adapty.io/documentation/adapty/adaptypaywall) со списком ID продуктов, идентификатором пейвола, Remote Config и рядом других свойств. |

## Получение конфигурации отображения пейвола, созданного в Paywall Builder \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\}

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

После получения пейвола проверьте, содержит ли он конфигурацию отображения — это признак того, что он создан с помощью Paywall Builder. Это определит способ отображения пейвола. Если конфигурация отображения есть, обрабатывайте пейвол как созданный в Paywall Builder; если нет — [обработайте его как Remote Config пейвол](present-remote-config-paywalls).

Для загрузки конфигурации отображения используйте метод `getPaywallConfiguration`.

```swift showLineNumbers

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** | опциональный | Передайте массив `AdaptyPaywallProducts` для оптимизации времени отображения продуктов на экране. Если передать `nil`, AdaptyUI автоматически загрузит необходимые продукты. |

:::note
Если вы используете несколько языков, узнайте, как добавить [локализацию Paywall Builder](add-paywall-locale-in-adapty-paywall-builder) и как правильно использовать коды локалей [здесь](localizations-and-locale-codes).
:::

После загрузки [покажите пейвол](ios-present-paywalls).

## Получение пейвола для аудитории по умолчанию для ускоренной загрузки \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\}

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

Для этого можно использовать метод `getPaywallForDefaultAudience`, который загружает пейвол указанного плейсмента для аудитории **All Users**. Однако важно понимать, что рекомендуемый подход — использовать метод `getPaywall`, как описано в разделе [Получение пейвола, созданного в Paywall Builder](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder) выше.

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

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

- **Потенциальные проблемы с обратной совместимостью**: если вам нужно показывать разные пейволы для разных версий приложения (текущей и будущих), могут возникнуть сложности. Придётся либо разрабатывать пейволы с поддержкой текущей (устаревшей) версии, либо мириться с тем, что пользователи на текущей (устаревшей) версии могут столкнуться с проблемами отображения пейволов.
- **Потеря таргетинга**: все пользователи будут видеть один и тот же пейвол, предназначенный для аудитории **All Users**, что означает потерю персонализированного таргетинга (в том числе по странам, маркетинговой атрибуции или собственным пользовательским атрибутам).

Если вы готовы принять эти недостатки ради более быстрой загрузки пейволов, используйте метод `getPaywallForDefaultAudience` следующим образом. В противном случае используйте `getPaywall`, описанный [выше](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder).
:::

```swift showLineNumbers
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
    }
}
```

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

| Параметр | Наличие | Описание |
|---------|--------|-----------|
| **placementId** | обязательный | Идентификатор [плейсмента](placements). Это значение вы указали при создании плейсмента в дашборде Adapty. |
| **locale** | <p>опциональный</p><p>по умолчанию: `en`</p> | <p>Идентификатор [локализации пейвола](add-remote-config-locale). Ожидается языковой код, состоящий из одного или нескольких субтегов, разделённых символом минуса (**-**). Первый субтег — язык, второй — регион.</p><p></p><p>Пример: `en` — английский, `pt-br` — бразильский португальский.</p><p></p><p>Подробнее о кодах локалей и рекомендациях по их использованию см. в разделе [Локализации и коды локалей](localizations-and-locale-codes).</p> |
| **fetchPolicy** | по умолчанию: `.reloadRevalidatingCacheData` | <p>По умолчанию SDK пытается загрузить данные с сервера и возвращает кэшированные данные в случае неудачи. Мы рекомендуем этот вариант, поскольку он гарантирует, что пользователи всегда получают актуальные данные.</p><p></p><p>Однако если у ваших пользователей нестабильное интернет-соединение, рассмотрите использование `.returnCacheDataElseLoad` для возврата кэшированных данных при их наличии. В этом случае пользователи могут получить не самые последние данные, но загрузка будет быстрее вне зависимости от качества соединения. Кэш регулярно обновляется, поэтому его безопасно использовать в течение сессии во избежание лишних сетевых запросов.</p><p></p><p>Кэш сохраняется при перезапуске приложения и очищается только при его переустановке или ручной очистке.</p> |

## Настройка ресурсов \{#customize-assets\}

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

Главные изображения и видео имеют предопределённые ID: `hero_image` и `hero_video`. В наборе пользовательских ресурсов вы обращаетесь к этим элементам по их ID и настраиваете их поведение.

Для других изображений и видео необходимо [задать пользовательский ID](custom-media) в дашборде Adapty.

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

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

:::important
Для использования этой функции обновите Adapty iOS SDK до версии 3.7.0 или выше.
:::

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

```swift showLineNumbers
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
    "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
)
```

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

## Настройка таймеров, заданных разработчиком \{#set-up-developer-defined-timers\}

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

```swift showLineNumbers
@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-часовом периоде, который начался с момента открытия пейвола пользователем.