Optimiser le chargement des flows et paywalls dans le SDK iOS

Un chargement fiable de flow ou de paywall sur iOS repose sur trois éléments : un rendu rapide, le retour de la variante ciblée selon l’audience, et un repli élégant en cas de réseau lent. Les règles ci-dessous couvrent le timing, la mise en cache et les stratégies de repli pour y parvenir.

Tip

Ces règles supposent que Adapty.activate() et Adapty.identify() ont déjà été résolus. Consultez Ordre des appels dans le SDK iOS.

Règles et pièges

FaireNe pas fairePourquoi
Récupérez le placement que vous êtes sur le point d’afficher, ou préchauffez le cache avec preloadFlows (SDK 4.1+).Déclencher vos propres appels concurrents getFlow au lancement.Une rafale de préchargement artisanale bloque le thread principal et produit un écran noir. preloadFlows est conçu pour ça et partage un seul budget de timeout sur tout le lot.
Appelez getFlow après que l’attribution a eu le temps de se résoudre — par exemple, 1 à 2 secondes après activate ou après le déclenchement de didLoadLatestProfile.Appeler getFlow dans App.init().L’attribution n’est pas encore arrivée. Le flow se résout sur l’audience par défaut et contourne silencieusement les segments et la personnalisation ASA.
Définissez un loadTimeout et configurez un paywall de secours pour chaque placement.Attendre getFlow indéfiniment.Sans timeout, les utilisateurs avec une mauvaise connexion voient un écran vide jusqu’à ce que le réseau réponde — ou ferment l’application.

Lorsque loadTimeout se déclenche sur n’importe quelle requête — y compris un simple getFlow — le SDK renvoie la variante mise en cache si elle existe, sinon il récupère la variante de l’audience par défaut (All Users) dans le temps restant. Le ciblage est perdu pour cette requête, pas simplement retardé : les segments et les audiences basées sur l’attribution ne s’appliquent pas au résultat.

Consultez Récupérer les paywalls et les produits pour la référence des paramètres fetchPolicy et loadTimeout, et Placements pour choisir le bon placement.

Précharger les placements

Info

preloadFlows et preloadFlowsForDefaultAudience sont disponibles à partir de la version 4.1 du SDK.

preloadFlows met en cache le JSON du flow à l’avance — une requête par placement. Vous l’utilisez ensuite comme d’habitude : getFlow pour le flow, getFlowConfiguration pour sa configuration de vue.

fetchPolicy détermine quelle couche un getFlow ultérieur lit en premier, pas s’il peut accéder au cache :

  • .returnCacheDataElseLoad lit d’abord la copie préchargée et n’accède au réseau que si rien n’est en cache. .returnCacheDataIfNotExpiredElseLoad(maxAge:) fait de même tant que la copie est plus récente que maxAge.
  • La valeur par défaut, .reloadRevalidatingCacheData, passe d’abord par le réseau et se rabat sur la copie préchargée en cas d’échec ou de timeout.

Le préchargement est utile dans les deux cas, mais différemment : une politique cache-first supprime la requête, tandis que la valeur par défaut la conserve tout en disposant d’une copie chaude en secours.

Utilisez cette méthode quand vous savez quels placements la session va nécessiter, mais que vous ne voulez pas les afficher tout de suite — par exemple, juste après la résolution de activate et identify, pour le flow derrière un bouton que l’utilisateur n’a pas encore tapé.

Paramètres :

  • placementIds (obligatoire) : les placements à précharger. Les IDs vides et en double sont ignorés.
  • loadTimeout (optionnel) : délai d’expiration en secondes pour l’ensemble du lot, non par placement. Par défaut 5 secondes, et les valeurs inférieures à 1 seconde sont relevées à 1 seconde.

Ce qu’il faut savoir sur le comportement :

  • La méthode ne lève une exception qu’après avoir essayé tous les placements, et l’erreur regroupe les échecs par placement. Un échec sur un placement n’interrompt pas les autres.
  • Si un placement expire ou échoue avec une erreur réseau, le SDK bascule sur la variante d’audience par défaut pour ce placement. Les autres échecs sont rapportés tels quels.
  • Si le délai expire avant que la récupération ciblée par audience soit terminée, le SDK tente quand même la variante d’audience par défaut dans le temps restant.
  • Le préchargement sert uniquement à alimenter le cache. Il ne retourne pas de contenu — vous appelez toujours getFlow pour l’afficher.

Ce que couvre un préchargement

Un flow s’affiche à l’écran par couches. Un préchargement couvre la première, exactement comme le fait getFlow :

CoucheRécupérée parMise en cache par un préchargement
JSON du flow — la variante choisie, ses identifiants de produits et la Remote ConfiggetFlowOui
Mise en page de l’UI — structure, styles et textes de l’écrangetFlowConfigurationNon
Images, y compris la première image fixe utilisée à la place d’un élément vidéogetFlowConfiguration, en arrière-planNon
Fichiers vidéoLe lecteur système, au moment du rendu de l’écranNon mis en cache par le SDK

getFlowConfiguration attend le layout, donc la première requête pour un layout donné coûte un aller-retour réseau, même après un préchargement. Le SDK conserve ensuite ce layout dans son propre cache disque, qui survit aux redémarrages de l’application et est lu avant tout appel réseau — le coût ne se répercute donc que sur la première requête, pas sur toutes. Une fois le layout disponible, le SDK commence à mettre les images en cache indépendamment de l’appel : il ne bloque pas l’affichage de l’écran, et aucun callback, méthode déléguée ou erreur ne signale la fin de cette opération.

Identifier quel placement a échoué

L’erreur levée est un AdaptyError unique couvrant tout le lot, avec le code networkFailed (2005). Pour voir les échecs individuels, consultez sa propriété preloadErrors — un dictionnaire indexé par ID de placement :

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

preloadErrors est nil pour toute erreur ne provenant pas d’un appel de préchargement ; traitez donc une valeur nil comme « pas un échec de préchargement » plutôt que comme « aucune erreur ».

Ignorer la segmentation d’audience

Pour préchauffer le cache sans attendre la segmentation d’audience, utilisez la variante d’audience par défaut :

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

Afficher les médias du premier écran depuis le bundle de l’application

Un flow télécharge ses images et vidéos depuis Adapty. Pour afficher instantanément les médias du premier écran, servez-les depuis le bundle de l’application. C’est une bonne façon de réutiliser des médias déjà inclus dans l’app, comme les visuels d’un onboarding natif existant.

  1. Dans le Flow & Paywall Builder, définissez un identifiant de média personnalisé sur l’image ou la vidéo. Le fichier que vous y importez reste en tant que solution de secours.
  2. Ajoutez le fichier au bundle de l’application.
  3. Lorsque vous appelez getFlowConfiguration, transmettez le fichier du bundle pour cet identifiant via 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
)

Les fichiers intégrés augmentent la taille de téléchargement de votre application, alors n’intégrez que les médias visibles en premier.

Les médias non intégrés s’affichent quand même immédiatement : la configuration de la vue contient une petite copie en basse résolution de chaque image, y compris l’image fixe d’une vidéo, et l’affiche jusqu’au chargement du fichier complet.

Pour la référence complète de assetsResolver, consultez Personnaliser les assets.

Optimiser pour une mauvaise connectivité

Pour les marchés où la connectivité est régulièrement mauvaise (zones rurales, transports, régions affectées par le routage) :

  • Définissez fetchPolicy: .returnCacheDataElseLoad sur chaque requête sauf la toute première.
  • Configurez un paywall de secours pour chaque placement dans l’Adapty Dashboard.
  • Définissez loadTimeout entre 3 et 5 secondes et acceptez le paywall de secours quand le délai expire.
  • N’attendez pas getProfile() pour afficher le flow. Appelez getFlow indépendamment pour qu’un profil lent ne bloque pas l’interface.