For the complete documentation index, see llms.txt. This page is also available as Markdown.

iOS — Installation

Cette page vous mène d'un projet Xcode vide à une intégration prête pour l'App Store, dans l'ordre. Les étapes 1 à 6 sont l'intégration elle-même ; les étapes 7 à 10 couvrent les utilisateurs américains, les tests, la release et les montées de version.

Chaque extrait Swift ci-dessous compile tel quel contre le paquet 2.0.0 publié, sauf ceux marqués fragment, qui se placent dans votre propre code.

1. Prérequis

Exigence

Deployment target iOS

15.0 ou plus, quel que soit le canal

Xcode

Vérifié avec Xcode 27.0 ; les versions antérieures n'ont pas été testées. Le paquet déclare les Swift tools 5.9, qui exigent Xcode 15 ou plus

Swift

5.9 ou plus

Sirdata

Un partner ID et un config ID, disponibles dans la Console Sirdata

Le binaire 2.0.0 lui-même est construit avec Xcode 26, la version figée dans la recette de build du SDK. C'est un framework statique avec une interface Objective-C ; l'interface de consentement est livrée sous forme de sources Swift que votre Xcode compile.

Le partner ID et le config ID désignent la configuration éditeur que le SDK télécharge au lancement : textes, thème, finalités, partenaires, périmètre et capping. Une modification de configuration dans la Console Sirdata prend effet sans nouvelle release de l'application.

Licence. Le SDK est un logiciel propriétaire, concédé sous licence et non vendu, sous la Sirdata CMP Mobile SDK Proprietary Licence v1.1, qui est aussi le fichier LICENSE des paquets Swift Package Manager et CocoaPods. Livrer le SDK dans une application mise à la disposition d'utilisateurs exige un abonnement valide et en cours à la Sirdata Consent Management Platform ; un abonnement pris par la Console Sirdata suffit, et aucun accord signé n'est requis (section 25.1). Sans abonnement, la licence est une licence d'évaluation de 90 jours : évaluation interne, développement, tests et intégration, sans distribution à des tiers ni sur un store d'applications (section 1.4). Abonnements : sirdata.com ; questions sur la licence : legal@sirdata.com.

2. Ajouter le SDK au projet

Utilisez Swift Package Manager ou CocoaPods : les deux livrent le framework du cœur et l'interface de consentement SwiftUI. Le XCFramework manuel n'a pas d'interface.

Swift Package Manager dans Xcode (recommandé)

  1. File → Add Package Dependencies…, puis saisissez https://github.com/SirDataFR/sirdata-cmp-ios-spm.

  2. Réglez la règle de dépendance sur Up to Next Major Version, à partir de 2.0.0.

  3. Ajoutez le produit SirDataCMP à la cible de votre application.

Swift Package Manager dans un Package.swift

Déclarez le paquet, puis le produit dans chaque cible qui l'utilise. Le libellé package: est le dernier composant de l'URL :

CocoaPods

Dans votre Podfile :

Lancez pod install, puis ouvrez le .xcworkspace, pas le .xcodeproj. Si CocoaPods ne trouve pas la version 2.0, lancez pod install --repo-update. Le pod fonctionne avec ou sans use_frameworks!.

Le pod s'appelle SirdataCMP, avec un d minuscule. Gardez la contrainte ~> 2.0 : les versions 1.x de ce pod sont un autre SDK Sirdata, abandonné, de 2020, construit à partir d'une autre base de code.

Manuel (XCFramework)

Téléchargez SirDataCMP-2.0.0.xcframework.zip depuis la page des releases, décompressez-le, glissez SirDataCMP.xcframework dans votre projet, et dans General → Frameworks, Libraries, and Embedded Content de votre cible, réglez-le sur Do Not Embed : c'est un framework statique, lié dans le binaire de votre application.

Cette archive ne contient que le module SirDataCMP du cœur, et aucun des fichiers de licence de l'étape 9. L'interface de consentement SwiftUI (SirDataCMPUI, ConsentView, utilisée à l'étape 4) est livrée sous forme de sources Swift par Swift Package Manager et CocoaPods ; utilisez l'un des deux si vous voulez l'interface intégrée.

Deux modules

Quel que soit le canal, vous importez deux modules :

Ils sont séparés parce que le framework binaire possède le nom de module SirDataCMP.

Si votre application lie Firebase Analytics par Swift Package Manager, lisez Transmission du consentement aux SDK partenaires avant d'aller plus loin : l'adaptateur de consentement a besoin que les classes de Firebase soient liées.

3. Initialiser le SDK

Initialisez le plus tôt possible, avant tout SDK publicitaire ou analytics : un SDK partenaire qui lit le stockage avant que la CMP ne se soit déclarée se comporte comme si aucune CMP n'était présente.

Trois règles :

  • Exactement une fois. En 2.0.0, un second initialize pendant que le SDK tourne termine l'application (la prochaine version l'ignore et le journalise). Pour passer à un autre partenaire ou à une autre configuration, appelez d'abord shutdown() ; IosCMPApi.shared.isInitialized() vous dit s'il tourne.

  • Sur le fil principal. App.init() et application(_:didFinishLaunchingWithOptions:) s'y exécutent tous les deux. Un appel depuis un autre fil est journalisé, et termine l'application sous debugMode (ci-dessous).

  • Avant tout autre appel au SDK. En 2.0.0, ceux-ci terminent l'application quand le SDK n'est pas initialisé : présenter ConsentView, getConsentState(), getConsentData(), getConsentUpdates(), getGoogleConsentState(), getLastForwardedConsentState(), getRegisteredAdapters(), getLastTcStringError(), discardPendingChanges(), acceptAll(), rejectAll(), saveConsent() et submitConsent(userAction:).

En 2.0.0, sur iOS, un mauvais usage termine l'application au lieu de lever une erreur : le SDK est écrit en Kotlin, et ses exceptions ne passent pas en Swift. La prochaine version (non publiée) le supprime : avant initialize, les getters renvoient une valeur neutre (rien de sélectionné, rien d'accordé, nil), acceptAll(), rejectAll(), saveConsent() et submitConsent(userAction:) lèvent une erreur Swift que vous pouvez attraper, un second initialize est ignoré et journalisé, et ConsentView affiche un message avec un bouton Fermer. Les trois règles restent la bonne intégration.

Les extraits utilisent le partenaire 1020 et la configuration "hmDnl", une configuration d'exemple. Remplacez-les par les identifiants de votre application, disponibles dans la Console Sirdata.

Application SwiftUI

Application UIKit

partnerId est un Int32 en Swift : écrivez Int32(id) si vous le détenez sous forme d'Int.

IABTCF_CmpSdkID est écrit dans UserDefaults.standard de façon synchrone pendant cet appel, avant tout travail réseau, comme l'exige la spécification IAB. Tout le reste — configuration éditeur, listes de partenaires, consentement stocké — se charge ensuite, de façon asynchrone.

Options de configuration

  • gdprDefaultApplies (par défaut true) ne sert qu'avant le chargement de la configuration, et seulement quand la locale de l'appareil ne porte pas de région. Une fois la configuration chargée, c'est l'API Sirdata qui décide si le RGPD s'applique.

  • debugMode (par défaut false) fait terminer l'application à un appel de initialize, shutdown ou setCcpaOptOut(optedOut:) fait hors du fil principal, au lieu de seulement le journaliser, pour que le défaut apparaisse dans vos propres builds de debug. Il n'a pas d'autre effet. Gardez-le sous #if DEBUG.

  • apiRoot, cacheApiRoot et consentApiRoot désignent par défaut les hôtes Sirdata (api., choices. et mychoice.consentframework.com). Laissez-les tels quels.

  • language(language:) est acceptée mais sans effet en 2.0.0. La langue de l'interface est celle que fixe votre configuration ; quand elle n'en fixe aucune, la langue préférée de l'appareil si l'API Sirdata la sert, puis la langue par défaut de la configuration, puis l'anglais.

Il n'y a pas d'option de thème sur iOS : couleurs, logo et position de la bannière viennent de votre configuration. Quand l'appareil est en mode sombre, les couleurs du mode sombre de la configuration s'appliquent si elle en définit.

4. Présenter l'interface de consentement

Laissez le SDK décider s'il faut la présenter. Ne testez pas la chaîne TC vous-même : un consentement partiel doit rouvrir la bannière, une fenêtre de capping active doit l'empêcher, et ni l'un ni l'autre ne se lit dans la chaîne.

SwiftUI

awaitConsentDisplayDecision() attend la configuration éditeur, puis applique la même cascade que la CMP web : applicabilité du RGPD, consentement stocké, cookie wall, les trois fenêtres de capping, et si le choix stocké couvre encore chaque finalité, partenaire et finalité éditeur actifs. Elle renvoie aussi comment présenter : un choix qui ne manque qu'au niveau des partenaires ouvre la bannière en mode « appliquer les choix », qui ne demande que ce qui reste à décider. Avec le cookie wall activé dans votre configuration, la bannière revient à chaque lancement tant que l'utilisateur n'a pas accordé la finalité 1.

Sur un réseau mort, l'attente dure jusqu'à ce que l'initialisation abandonne, ce qui peut prendre la somme des timeouts HTTP. Derrière un écran de lancement, bornez-la — passé l'échéance, vous obtenez la décision en l'état, provisoire si la configuration n'est pas arrivée (fragment) :

ConsentView affiche tout le parcours (bannière → finalités → partenaires), habillé selon votre configuration. Son initialiseur est ConsentView(onFinish:initialScreen:workflow:) : onFinish est appelé quand l'utilisateur a terminé, et initialScreen: .purposes ouvre directement sur l'écran des préférences. La vue émet elle-même cmpuiclosed à sa fermeture. Appelez notifyBannerShown() chaque fois que vous la présentez.

UIKit

Présentez ConsentView dans un UIHostingController, en plein écran sur un fond transparent : la vue dessine son propre fond assombri et positionne elle-même la bannière.

Avant de livrer cette présentation plein écran, lisez le problème connu de 2.0.0 à la fin de la section suivante : elle n'a aucune issue quand la configuration n'a pas pu être chargée.

Fermer la feuille sans répondre

Dans une .sheet, l'utilisateur peut faire glisser la bannière vers le bas. Cela la ferme sans rien enregistrer : le SDK le signale à Sirdata comme une fermeture sans choix, émet cmpuiclosed, et la bannière s'affiche de nouveau au lancement suivant. Pour l'empêcher — avec un cookie wall, par exemple —, désactivez le geste sur la vue (fragment) :

La présentation plein écran UIKit ci-dessus n'a pas ce geste.

Problème connu de 2.0.0 : aucune issue tant que la configuration manque. Si la configuration n'a pas pu être chargée à ce lancement — l'appareil est hors ligne, par exemple —, la décision peut quand même demander la bannière (raison configNotLoaded), mais ConsentView n'affiche alors qu'un indicateur de chargement, sans bouton de fermeture. Dans une simple .sheet, l'utilisateur peut encore la faire glisser vers le bas. Avec .interactiveDismissDisabled(), ou dans la présentation plein écran UIKit ci-dessus, rien ne la ferme. Si vous utilisez l'une ou l'autre, ne présentez la vue qu'une fois la configuration chargée. La prochaine version (non publiée) corrige cela : ConsentView affiche un message et un bouton Fermer quand la configuration n'a pas pu être chargée, et un bouton Fermer sous l'indicateur de chargement après cinq secondes. Avec UIKit, faites-en la première ligne de presentConsent(workflow:), pour qu'elle couvre aussi la réouverture de l'étape 6 (fragment) :

5. Lire le consentement dans votre code

Valeurs

Ces getters lisent les valeurs stockées, celles que lisent aussi les SDK partenaires : les clés IAB de UserDefaults.standard (IABTCF_…, IABGPP_…, et IABUSPrivacy_String dès qu'un choix US existe). Transmission du consentement aux SDK partenaires les liste. isGdprApplies() est la réponse de l'API Sirdata une fois la configuration chargée, et une estimation d'après la région de l'appareil avant.

Certaines clés existent avant tout choix. initialize écrit IABTCF_CmpSdkID, IABTCF_CmpSdkVersion et IABTCF_PolicyVersion. Une fois la configuration chargée, le SDK écrit IABTCF_gdprApplies, de nouveau IABTCF_PolicyVersion (tirée de la liste de partenaires chargée), IABTCF_PublisherCC, IABTCF_PurposeOneTreatment, IABTCF_UseNonStandardTexts, les chaînes de bits éditeur (IABTCF_PublisherConsent, IABTCF_PublisherLegitimateInterests et les deux clés IABTCF_PublisherCustomPurposes…) et, pour un utilisateur américain, les clés GPP avec la section US. IABTCF_TCString et les consentements par finalité et par partenaire (IABTCF_PurposeConsents, IABTCF_VendorConsents…) n'apparaissent qu'une fois un choix enregistré.

Réagir aux changements

Un flow Kotlin ne se collecte pas depuis Swift : observez le compteur de mises à jour du SDK avec un UpdateCounterWatcher. Créez-le après initialize, gardez une référence vers lui, et fermez-le quand vous avez terminé.

Le callback s'exécute sur le fil principal. Il se déclenche à chaque changement de la sélection, y compris les bascules dans l'interface de consentement ouverte qui ne sont pas encore enregistrées : relisez donc les valeurs stockées à chaque fois plutôt que de compter les appels ; elles ne changent que quand l'utilisateur enregistre. UserDefaults.didChangeNotification fonctionne aussi, mais se déclenche à chaque écriture dans les defaults de l'application.

Un choix US — enregistré sur l'écran US, ou avec setCcpaOptOut(optedOut:) — ne fait pas avancer le compteur : relisez getUspString() et getGppString() à la fermeture de l'interface de consentement (dans onFinish), et juste après vos propres appels à setCcpaOptOut.

L'API TCF in-app (tcfApi()) a une commande addEventListener, mais en 2.0.0 son callback ne dit pas quel événement a eu lieu : relisez-y aussi les valeurs stockées.

IosCMPApi.shared.getGoogleConsentState() renvoie les signaux Google que le SDK dérive du choix TCF stocké (adStorageGranted, analyticsStorageGranted, adUserDataGranted, adPersonalizationGranted). Le SDK transmet lui-même le consentement à Firebase Analytics : voir Transmission du consentement aux SDK partenaires.

Votre propre écran de consentement

À la place de ConsentView, un écran à vous peut enregistrer un choix avec try await IosCMPApi.shared.acceptAll() ou rejectAll(). Chacune renvoie un ConsentResult : ConsentResult.Success, ou ConsentResult.Error avec un message. Appelez notifyBannerShown() quand votre écran apparaît et notifyBannerClosed() quand il se ferme, pour que l'API TCF in-app émette cmpuishown et cmpuiclosed. recordAskLater() enregistre un « me le redemander plus tard » : la bannière reste masquée pendant une heure. Chaque méthode figure dans la Référence.

6. Rouvrir depuis un écran de réglages

Les utilisateurs doivent pouvoir modifier leurs choix à tout moment. Donnez-leur un point d'entrée — une ligne « Choix de confidentialité » dans vos réglages — qui présente la vue dans le workflow manuel :

Avec UIKit, appelez presentConsent(workflow: .manualDisplay) de l'étape 4.

Dans le workflow manuel, la bannière a une croix de fermeture en haut et un bouton « Tout refuser », quels que soient le type et le style de refus que fixe votre configuration, et les écrans finalités et partenaires montrent les choix enregistrés. À son apparition, la vue relance la fenêtre de capping de votre configuration et signale une réouverture (load:revisit) : n'appelez pas recordPrompt() vous-même.

7. Utilisateurs américains

Quand le RGPD ne s'applique pas, le SDK ne demande jamais à afficher la bannière : awaitConsentDisplayDecision() renvoie shouldDisplay == false, avec la raison gdprNotApplies. Un utilisateur américain ne voit donc rien tant que votre application n'ouvre pas l'interface de consentement.

isCcpaApplies() vous dit si le régime US s'applique : la réponse de l'API Sirdata une fois la configuration chargée, la région de l'appareil avant. Quand il vaut true, ConsentView affiche l'écran US du SDK à la place de la bannière TCF, quel que soit le workflow. L'enregistrer enregistre le choix d'opposition de l'utilisateur : le SDK écrit IABUSPrivacy_String et réencode les sections US de la chaîne GPP. Jusque-là, IABUSPrivacy_String est absente ; les clés GPP, avec la section US, sont écrites dès que la configuration est chargée, avec des valeurs par défaut tant que l'utilisateur n'a pas choisi. Un choix US ne fait pas avancer le compteur de getConsentUpdates() (étape 5).

Montrez donc le point d'entrée de l'étape 6 aux utilisateurs américains aussi. Si vous construisez plutôt votre propre écran US, appelez IosCMPApi.shared.setCcpaOptOut(optedOut:) sur le fil principal, et seulement avec le choix que l'utilisateur a réellement fait — jamais à sa place.

8. Tester et vérifier l'intégration

Pour rejouer un premier lancement, supprimez l'application, ou appelez IosCMPApi.shared.clearConsent() et relancez. Appelez-le aussi chaque fois que vous passez à un autre partenaire ou à une autre configuration : un choix stocké appartient à l'éditeur qui l'a collecté.

L'application du RGPD est décidée par l'API Sirdata, d'après le pays de l'adresse IP de l'appareil et votre configuration — pas d'après les réglages de région de l'appareil. Là où le RGPD ne s'applique pas, la bannière ne s'affiche pas (raison gdprNotApplies).

Dans un build de debug, vérifiez chaque point dans l'ordre :

  1. Juste après initialize, UserDefaults.standard.integer(forKey: "IABTCF_CmpSdkID") vaut 92.

  2. Au premier lancement, la décision a shouldDisplay == true et la bannière apparaît avec les textes, les couleurs et le logo de votre configuration. Les écrans finalités et partenaires s'ouvrent. Avant tout choix, une fois la configuration chargée, IABTCF_gdprApplies vaut 1 et IABTCF_TCString est absente.

  3. Après Tout accepter, IABTCF_TCString, IABTCF_PurposeConsents, IABTCF_VendorConsents et IABGPP_HDR_GppString sont renseignées, et IABUSPrivacy_String est absente.

  4. Après une relance, la bannière ne s'affiche plus.

  5. La réouverture de l'étape 6 montre la croix de fermeture, le bouton « Tout refuser » et les choix enregistrés ; un nouveau choix remplace l'ancien.

  6. ping réussit et indique cmpStatus loaded.

  7. La console Xcode n'affiche aucune ligne commençant par [CMP]. Il n'en apparaît une que lorsque quelque chose est à corriger : un appel hors du fil principal, un adaptateur de consentement qui n'a pas pu transmettre un choix, une chaîne TC stockée qui n'a pas pu être relue.

  8. Un build Release tourne sur un vrai appareil.

Les clés des points 1 à 3, et le point 6, se vérifient depuis le code (fragment). Lisez IABTCF_CmpSdkID juste après initialize ; lancez le reste une fois la configuration chargée — depuis un bouton de debug, par exemple : jusque-là, ping répond avec cmpStatus stub.

Si la bannière n'apparaît jamais, la décision le dit avant tout log (fragment) :

Une fenêtre de capping active (cappingActive, cappingAskLater), un consentement stocké qui couvre encore tout (consentOk) ou un RGPD non applicable (gdprNotApplies) sont des raisons normales pour que la bannière ne s'affiche pas.

Si la configuration ne se charge pas — IosCMPApi.shared.tcfApi().isCmpLoaded() reste à false quelques secondes après le lancement —, IosCMPApi.shared.getInitError() renvoie le message d'erreur du chargement échoué ; un partner ID ou un config ID inconnu et une panne réseau y aboutissent tous les deux. Le SDK ne le journalise pas. Lisez-le à ce moment-là, pas dès le retour d'awaitConsentDisplayDecision() : en 2.0.0, à cet instant, il peut encore valoir nil après un échec. La prochaine version le renseigne avant le retour d'awaitConsentDisplayDecision(). Voir aussi Logs et Dépannage.

9. Préparer la release

  • Vos propres identifiants. Remplacez les partner ID et config ID d'exemple par ceux de votre application.

  • debugMode dans les builds de debug uniquement. Il termine l'application sur une violation du fil principal, et le SDK ne regarde pas le type de build : gardez-le sous #if DEBUG.

  • Licence. Livrer l'application exige un abonnement valide et en cours à la Sirdata Consent Management Platform ; un abonnement pris par la Console Sirdata suffit (étape 1).

  • Mentions des composants tiers. Le SDK embarque des composants open source sous Apache License 2.0 et sous Boost Software License 1.0. Quand vous distribuez votre application, reproduisez le fichier de mentions du SDK et le texte de ces licences, et mettez-les à la disposition de vos utilisateurs — dans l'écran des remerciements de votre application, par exemple. C'est une condition de l'Apache License, et de la section 26.1(b) du LICENSE du SDK. Avec Swift Package Manager, ils sont dans le paquet, sous NOTICE et THIRD-PARTY-LICENSES/ ; avec CocoaPods, dans Pods/SirdataCMP/ sous NOTICE-ios et THIRD-PARTY-LICENSES/ ; avec le XCFramework manuel, prenez-les dans le dépôt du paquet sur GitHub.

  • Manifeste de confidentialité. Le SDK 2.0.0 ne livre pas de manifeste de confidentialité Apple (PrivacyInfo.xcprivacy). Il lit et écrit UserDefaults.standard, l'une des catégories d'API (NSPrivacyAccessedAPICategoryUserDefaults) que couvre la documentation d'Apple sur les required reason APIs (consultée le 2026-10-05). Tenez-en compte pour votre soumission à l'App Store, et posez vos questions à votre contact Sirdata.

  • Détails de confidentialité de l'app. Les privacy details que vous renseignez dans App Store Connect incluent les pratiques des SDK tiers de votre application (consulté le 2026-10-05), celui-ci compris. Il envoie des requêtes à api.consentframework.com, choices.consentframework.com et mychoice.consentframework.com.

10. Monter de version

Depuis Swift Package Manager 1.2.0. « Up to Next Major Version » ne franchit jamais une version majeure : une règle posée à partir de 1.2.0 reste en 1.x. Faites-la partir de 2.0.0 : dans Xcode, dans l'onglet Package Dependencies de votre projet ; dans un Package.swift, from: "2.0.0". Relevez ensuite votre deployment target à iOS 15.0 s'il est plus bas. Aucune API publique n'a été supprimée ni renommée en 2.0.0 : votre code n'a besoin d'aucun changement ; Versions liste ce qui a changé de comportement.

Depuis le pod SirdataCMP de 2020 (1.x). C'est un autre SDK, construit à partir d'une autre base de code. Retirez-le, ainsi que le code qui l'appelle, puis intégrez ce SDK à partir de l'étape 2, avec pod 'SirdataCMP', '~> 2.0'.

Gardez les deux modules à la même version. La couche SwiftUI et le framework binaire sont publiés ensemble, et les deux gestionnaires de paquets les gardent alignés. Si Xcode signale qu'un type n'a pas un membre qu'utilise le code du SDK, résolvez à nouveau le paquet, et ne mélangez pas une copie locale avec une version publiée.

Pour continuer

Mis à jour

Ce contenu vous a-t-il été utile ?