Optimizar la obtención de flows y paywalls en el SDK de iOS

Una obtención fiable de un flow o paywall en iOS hace tres cosas: renderiza rápido, devuelve la variación con la audiencia configurada y recurre al respaldo sin problemas cuando la red es lenta. Las reglas que se explican a continuación cubren los patrones de temporización, caché y respaldo para conseguirlo.

Tip

Las reglas asumen que Adapty.activate() y Adapty.identify() ya se han resuelto. Consulta Orden de llamadas en el SDK de iOS.

Reglas y errores comunes

Haz estoNo hagas estoPor qué
Obtén el placement que vas a mostrar, o precarga la caché con preloadFlows (SDK 4.1+).Lances tus propias llamadas concurrentes getFlow al arrancar.Una ráfaga de prefetch manual bloquea el hilo principal y produce una pantalla en negro. preloadFlows está diseñado para esto y comparte un único presupuesto de tiempo de espera para todo el lote.
Llama a getFlow después de que la atribución haya tenido tiempo de resolverse — por ejemplo, 1–2 segundos después de activate o tras que se dispare didLoadLatestProfile.Llamar a getFlow en App.init().La atribución aún no ha llegado. El flow se resuelve contra la audiencia por defecto y silenciosamente omite los segmentos y la personalización de ASA.
Establece un loadTimeout y configura un paywall de respaldo para cada placement.Esperar a getFlow indefinidamente.Sin un tiempo de espera, los usuarios con mala conectividad ven una pantalla en blanco hasta que la red se resuelva — o cierran la app.

Cuando loadTimeout se dispara en cualquier solicitud de carga — incluido un simple getFlow — el SDK devuelve la variación en caché si existe; de lo contrario, obtiene la variación de la audiencia predeterminada (All Users) dentro del tiempo restante. La segmentación se pierde para esa solicitud, no se retrasa: los segmentos y las audiencias basadas en atribución no se aplican al resultado.

Consulta Obtener paywalls y productos para la referencia de los parámetros fetchPolicy y loadTimeout, y Placements para elegir el placement adecuado.

Precargar placements

Info

preloadFlows y preloadFlowsForDefaultAudience están disponibles a partir de la versión 4.1 del SDK.

preloadFlows almacena en caché el JSON del flow con antelación — una solicitud por placement. Luego lo usas de la forma habitual: getFlow para el flow y getFlowConfiguration para su configuración de vista.

fetchPolicy determina qué capa lee primero un getFlow posterior, no si puede acceder a la caché en absoluto:

  • .returnCacheDataElseLoad lee primero la copia precargada y solo va a la red si no hay nada en caché. .returnCacheDataIfNotExpiredElseLoad(maxAge:) hace lo mismo mientras la copia sea más reciente que maxAge.
  • El valor predeterminado, .reloadRevalidatingCacheData, va primero a la red y cae de vuelta a la copia precargada cuando la solicitud falla o expira.

Una precarga resulta útil en ambos casos, pero de forma distinta: una política de caché primero elimina la solicitud, mientras que la predeterminada la mantiene y obtiene una copia en caliente como respaldo.

Úsalo cuando sepas qué placements necesitará la sesión pero no quieras mostrarlos todavía — por ejemplo, justo después de que resuelvan activate e identify, para el flow detrás de un botón que el usuario aún no ha pulsado.

Parámetros:

  • placementIds (obligatorio): los placements a precargar. Los IDs en blanco y duplicados se ignoran.
  • loadTimeout (opcional): tiempo de espera en segundos para todo el lote, no por placement. El valor predeterminado es 5 segundos, y los valores por debajo de 1 segundo se elevan a 1 segundo.

Comportamiento que debes conocer:

  • El método solo lanza un error tras intentarlo con todos los placements, y el error agrupa los fallos individuales de cada placement. Un fallo en un placement no detiene a los demás.
  • Si un placement supera el tiempo límite o falla por un error de red, el SDK recurre a la variación de audiencia predeterminada para ese placement. El resto de fallos se notifican tal cual.
  • Si se agota el tiempo límite antes de que complete la obtención de la audiencia segmentada, el SDK aún intenta la variación de audiencia predeterminada dentro del tiempo restante.
  • La precarga solo calienta la caché. No devuelve contenido: para mostrarlo, sigue siendo necesario llamar a getFlow.

Lo que cubre una precarga

Un flow llega a la pantalla en capas. Una precarga cubre la primera, exactamente igual que getFlow:

CapaObtenida porCalentada por una precarga
Flow JSON — la variante elegida, sus IDs de producto y el Remote ConfiggetFlowSí
Diseño de UI — la estructura, el estilo y el texto de la pantallagetFlowConfigurationNo
Imágenes, incluido el fotograma estático que sustituye a un elemento de vídeogetFlowConfiguration, en segundo planoNo
Archivos de vídeoEl reproductor del sistema, mientras se renderiza la pantallaEl SDK no los almacena en caché

getFlowConfiguration espera el layout, por lo que la primera solicitud para un layout determinado tiene el coste de un viaje de ida y vuelta incluso después de una precarga. El SDK guarda ese layout en su propia caché de disco, que sobrevive a los reinicios de la app y se lee antes de cualquier llamada de red, de modo que el coste recae en la primera solicitud y no en todas. Una vez que el SDK tiene el layout, comienza a cachear las imágenes de forma independiente a la llamada: no bloquea la pantalla, y no hay ningún callback, método delegado ni error que informe de cuándo termina.

Descubre qué placement falló

El error lanzado es un único AdaptyError que cubre todo el lote, con el código networkFailed (2005). Para ver los fallos individuales, lee su propiedad preloadErrors — un diccionario cuya clave es el ID del placement:

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

preloadErrors es nil para cualquier error que no provenga de una llamada de precarga, así que trata un valor nil como “no es un fallo de precarga” en lugar de “sin fallos”.

Omitir la segmentación de audiencias

Para calentar la caché sin esperar a la segmentación de audiencias en absoluto, usa la variante de audiencia predeterminada:

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

Mostrar medios de la primera pantalla desde el bundle de la app

Un flow descarga sus imágenes y vídeos desde Adapty. Para mostrar los medios de la primera pantalla de forma instantánea, sírvelos desde el bundle de la app. Es una buena forma de reutilizar medios que ya incluyes en la app, como los visuales de un onboarding nativo existente.

  1. En el Flow & Paywall Builder, asigna un ID de medio personalizado a la imagen o vídeo. El archivo que subas allí se mantendrá como respaldo.
  2. Añade el archivo al bundle de tu app.
  3. Cuando llames a getFlowConfiguration, pasa el archivo del bundle para ese ID a través de assetsResolver:
// "welcome_video" is the custom media ID set in the Flow & Paywall Builder
let bundledAssets: [String: AdaptyCustomAsset] = [
    "welcome_video": .video(
        .file(
            url: Bundle.main.url(forResource: "welcome", withExtension: "mp4")!,
            preview: .uiImage(value: UIImage(named: "welcome_poster")!),
            resolution: CGSize(width: 1080, height: 1920)
        )
    ),
]

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

Los archivos incluidos en el bundle aumentan el tamaño de descarga de tu app, así que incluye solo los archivos multimedia que el usuario ve al principio.

Los archivos multimedia que no incluyas en el bundle aparecen igualmente de inmediato: la configuración de la vista lleva una copia de baja resolución de cada imagen, incluido el fotograma estático de cada vídeo, y la muestra hasta que carga el archivo completo.

Para la referencia completa de assetsResolver, consulta Personalizar assets.

Ajustes para conectividad deficiente

Para mercados con conectividad habitualmente deficiente (zonas rurales, transporte, regiones con problemas de enrutamiento):

  • Establece fetchPolicy: .returnCacheDataElseLoad en cada fetch excepto el primero.
  • Configura un paywall de respaldo para cada placement en el Adapty Dashboard.
  • Establece loadTimeout entre 3 y 5 segundos y acepta el paywall de respaldo cuando se agote el tiempo.
  • No bloquees la visualización del flow esperando a getProfile(). Llama a getFlow de forma independiente para que un perfil lento no bloquee la interfaz.