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
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é)
File → Add Package Dependencies…, puis saisissez
https://github.com/SirDataFR/sirdata-cmp-ios-spm.Réglez la règle de dépendance sur Up to Next Major Version, à partir de 2.0.0.
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
initializependant 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'abordshutdown();IosCMPApi.shared.isInitialized()vous dit s'il tourne.Sur le fil principal.
App.init()etapplication(_:didFinishLaunchingWithOptions:)s'y exécutent tous les deux. Un appel depuis un autre fil est journalisé, et termine l'application sousdebugMode(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()etsubmitConsent(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éfauttrue) 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éfautfalse) fait terminer l'application à un appel deinitialize,shutdownousetCcpaOptOut(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,cacheApiRootetconsentApiRootdésignent par défaut les hôtes Sirdata (api.,choices.etmychoice.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.
Google Consent Mode
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 :
Juste après
initialize,UserDefaults.standard.integer(forKey: "IABTCF_CmpSdkID")vaut92.Au premier lancement, la décision a
shouldDisplay == trueet 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_gdprAppliesvaut1etIABTCF_TCStringest absente.Après Tout accepter,
IABTCF_TCString,IABTCF_PurposeConsents,IABTCF_VendorConsentsetIABGPP_HDR_GppStringsont renseignées, etIABUSPrivacy_Stringest absente.Après une relance, la bannière ne s'affiche plus.
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.
pingréussit et indiquecmpStatusloaded.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.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.
debugModedans 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
LICENSEdu SDK. Avec Swift Package Manager, ils sont dans le paquet, sousNOTICEetTHIRD-PARTY-LICENSES/; avec CocoaPods, dansPods/SirdataCMP/sousNOTICE-iosetTHIRD-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 écritUserDefaults.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.cometmychoice.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
Transmission du consentement aux SDK partenaires — la partie qui fait fonctionner la publicité
Référence — chaque méthode et chaque événement
Logs — ce que le SDK écrit dans la console
Dépannage — les erreurs que les intégrateurs rencontrent réellement
Versions — ce qui a changé à chaque version
Mis à jour
Ce contenu vous a-t-il été utile ?
