iOS — Reference
Every method and event exposed by the iOS SDK. Setup and the recommended integration order live in Setup.
iOS SDK — IosCMPApi
The primary interface for iOS publishers. All methods delegate to the IosCMPManager singleton.
import SirDataCMP, then call through IosCMPApi.shared. The signatures below are written as Swift sees them in the framework's exported header: Kotlin Int is Int32, Long is Int64, and a Kotlin suspend function is both async throws and a completionHandler: variant. The only error those variants pass on is a Kotlin CancellationException — in the next release, acceptAll, rejectAll, saveConsent and submitConsent also pass on the IllegalStateException raised before initialize.
Call initialize exactly once, on the main thread, before any other SDK call. Kotlin exceptions are not converted to Swift errors: a misuse that throws in Kotlin terminates the app. That is the case of a second initialize (without shutdown() in between), and of any of these calls before initialize: getConsentState(), getConsentData(), getConsentUpdates(), getLastTcStringError(), discardPendingChanges(), getGoogleConsentState(), getLastForwardedConsentState(), getRegisteredAdapters(), acceptAll(), rejectAll(), saveConsent(), submitConsent(userAction:), and creating a ConsentView. This is 2.0.0 behaviour. In the next release (unreleased) none of these terminates the app: the getters return a neutral value, the four submissions throw a Swift error, a second initialize is ignored and logged, and ConsentView shows a message with a Close button.
Initialization
initialize
func initialize(partnerId: Int32, configId: String)
Initialize with partner credentials. Main thread only. Writes IABTCF_CmpSdkID, IABTCF_CmpSdkVersion and IABTCF_PolicyVersion to NSUserDefaults immediately, then loads the publisher configuration asynchronously; the keys written once it has loaded, before any choice, are listed in Setup. A second call without shutdown() terminates the app in 2.0.0; the next release ignores it and logs it.
initialize
func initialize(config: IosCMPConfig)
Same, with a full configuration object — see IosCMPConfig below.
isInitialized
func isInitialized() -> Bool
Returns true once initialize has been called, before the configuration has loaded.
getInitError
func getInitError() -> String?
nil while the configuration loads and after it loaded; the error message once a load has failed (unknown config ID, network down…). Cleared by the next initialize. In 2.0.0 it is set a moment after getConsentState() turns READY; the next release sets it before, so it is there when awaitConsentDisplayDecision() returns. The failure is not logged on iOS — see Logging.
shutdown
func shutdown()
Clears in-memory state and cancels a configuration load in flight. Stored consent stays in NSUserDefaults. Main thread only.
Banner Events
notifyBannerShown
func notifyBannerShown()
Fires cmpuishown event. Call it each time you present ConsentView, just before presenting it.
notifyBannerClosed
func notifyBannerClosed()
Fires cmpuiclosed to TCF and GPP listeners. ConsentView calls it itself when it finishes or is dismissed: call it only for a consent UI of your own.
Consent Submission
All five need an initialized SDK.
acceptAll
func acceptAll() async throws -> ConsentResult
ConsentResult
Accept all purposes, vendors, and features.
rejectAll
func rejectAll() async throws -> ConsentResult
ConsentResult
Reject all purposes, vendors, and features.
saveConsent
func saveConsent() async throws -> ConsentResult
ConsentResult
Save current selections.
submitConsent
func submitConsent(userAction: UserActionResponse) async throws -> ConsentResult
ConsentResult
Records the current selections and reports them with the given answer.
discardPendingChanges
func discardPendingChanges()
—
Discards the selections changed since the last recorded choice. Call it right before submitting when the user declines to apply pending changes, as the "do not apply" button of the apply-choices banner does.
Each recorded choice fires useractioncomplete to TCF and GPP listeners and forwards the Google consent signals to the consent adapters.
Consent State Queries
getTcString
func getTcString() -> String
IAB TC String
getGppString
func getGppString() -> String
GPP String
getUspString
func getUspString() -> String
USP String — empty when no US choice has been recorded
getAddtlConsent
func getAddtlConsent() -> String
Additional Consent String
isGdprApplies
func isGdprApplies() -> Bool
GDPR applicability — context.gdprApplies from the API once loaded, device geo before
isCcpaApplies
func isCcpaApplies() -> Bool
US Privacy applicability — context.ccpaApplies from the API once the configuration has loaded (from the visitor's country and US state), device geo before
shouldCollectConsent
func shouldCollectConsent() -> Bool
Web checkConsent() cascade, answered immediately (provisional before the config lands)
getConsentDisplayDecision
func getConsentDisplayDecision() -> ConsentDisplayDecision
shouldDisplay + workflow + reason, also immediate — see Display decision
awaitConsentDisplayDecision
func awaitConsentDisplayDecision() async throws -> ConsentDisplayDecision
Waits for the config, then decides. Swift: try await
awaitConsentDisplayDecision
func awaitConsentDisplayDecision(timeoutMillis: Int64) async throws -> ConsentDisplayDecision
Same, bounded
recordPrompt / recordAskLater
func recordPrompt() / func recordAskLater()
Restart the cappingInDays window (only for a re-open the user asked for; ConsentView with .manualDisplay already does it) / record an explicit "ask me later", which hides the banner for one hour, a fixed duration, and records no consent. Both do nothing before initialize
getConsentState
func getConsentState() -> any Kotlinx_coroutines_coreStateFlow
Observable state flow — observe it with ConsentStateWatcher. Needs an initialized SDK
getConsentData
func getConsentData() -> ConsentData
Full consent data. Needs an initialized SDK
getConsentUpdates
func getConsentUpdates() -> any Kotlinx_coroutines_coreStateFlow
Counter bumped on every change to the selections — each toggle in the consent UI, before the user saves, as well as each recorded choice. A US choice (the US screen, or setCcpaOptOut) does not bump it: re-read getUspString() and getGppString() when the consent UI closes. A Kotlin flow cannot be collected from Swift: observe it with UpdateCounterWatcher. Needs an initialized SDK
getLastTcStringError
func getLastTcStringError() -> String?
Outcome of the last server archive of a recorded choice (/consent-string): nil when it succeeded or none has run, otherwise a message starting with /consent-string. Set in the background after submitConsent returns. Despite its name, it does not report on the TC string, which is encoded on the device. Needs an initialized SDK
getPurposeConsents
func getPurposeConsents() -> String
Purpose consents bit field
getVendorConsents
func getVendorConsents() -> String
Vendor consents bit field
hasPurposeConsent
func hasPurposeConsent(purposeId: Int32) -> Bool
Check purpose consent
hasVendorConsent
func hasVendorConsent(vendorId: Int32) -> Bool
Check vendor consent
Google Consent Mode and adapters
All three need an initialized SDK.
getGoogleConsentState
func getGoogleConsentState() -> GoogleConsentState
The Google consent signals computed from the current selections: what the adapters would receive
getLastForwardedConsentState
func getLastForwardedConsentState() -> GoogleConsentState?
What was actually forwarded to the adapters, or nil when no choice has been recorded since initialize
getRegisteredAdapters
func getRegisteredAdapters() -> [String]
The adapters whose SDK is linked into the app: "Firebase Analytics", "AppsFlyer", "Adjust", "Branch"
GoogleConsentState carries adStorageGranted, analyticsStorageGranted, adUserDataGranted, adPersonalizationGranted, personalizationStorageGranted, functionalityStorageGranted, securityStorageGranted, isSubjectToGDPR, hasConsentForDataUsage and adSignalsFromTcf — true when the configuration leaves the three ad signals to Google, in which case the Firebase adapter does not send them. See Sharing consent with vendor SDKs.
Observing changes from Swift
The two Kotlin flows above are observed through watchers. Each calls its block on the main thread; keep the watcher alive while you need it, and call close() when done. Calling watch again replaces the previous block.
UpdateCounterWatcher
init(flow: any Kotlinx_coroutines_coreStateFlow), func watch(block: @escaping (KotlinLong) -> Void), func close()
For getConsentUpdates(). Skips the current value: the block runs on the next change, not at startup. A burst of changes, such as one tap on a stack, is batched.
ConsentStateWatcher
init(flow: any Kotlinx_coroutines_coreStateFlow), func watch(block: @escaping (ConsentState) -> Void), func close()
For getConsentState(). Delivers the current state, then every change.
IAB API Access
tcfApi()
TcfApiHandler
IAB TCF CMP API v2
gppApi()
GppApiHandler
GPP API
uspApi()
UspApiHandler
USP/CCPA API
The commands and their data are the same as on Android — see the command tables in Reference — Android. The TCF and GPP handlers call back on the main thread; getUspData calls back synchronously, on the calling thread. Their Swift signatures:
The success flag is a KotlinBoolean: read it with success.boolValue. TCF listener callbacks carry no eventStatus in 2.0.0 — see the in-app command API.
CCPA Opt-Out
setCcpaOptOut(optedOut: Bool)
Records the user's "Do Not Sell" choice: writes IABUSPrivacy_String and, once the SDK is initialized, re-encodes the GPP string (sections 6 and 7). Call it from a control the user operates, never on their behalf. Main thread only. The consent UI's US screen calls it when the user saves. It does not bump the getConsentUpdates() counter
isCcpaOptedOut() -> Bool
Returns opt-out status
Data Management
clearConsent()
Clears ALL persisted consent from NSUserDefaults
IosCMPConfig — iOS Configuration
partnerId
Int32
required — your Sirdata partner ID
configId
String
required — your Sirdata config ID
language
String?
nil — accepted, no effect in 2.0.0
apiRoot
String
"https://api.consentframework.com/api/v1/public"
cacheApiRoot
String
"https://choices.consentframework.com/api/v1/public"
consentApiRoot
String
"https://mychoice.consentframework.com/api/v1/public"
debugMode
Bool
false — main-thread violations throw, which terminates the app
gdprDefaultApplies
Bool
true — see below
The defaults are Kotlin defaults, which Swift does not see: the IosCMPConfig initializer takes every argument — partnerId:configId:language:apiRoot:cacheApiRoot:consentApiRoot:debugMode:gdprDefaultApplies:. Use the builder instead.
languageis accepted but read by nothing in 2.0.0. The UI language is the one pinned in the publisher configuration in the Sirdata Console, if any; otherwise the device language, when the SDK supports it; otherwise the configuration's default language; otherwise English.debugModeonly changes the main-thread contract: a call toinitialize,shutdownorsetCcpaOptOutoff the main thread throws instead of being logged — and on iOS that terminates the app. Debug builds only.gdprDefaultAppliesis the answerisGdprApplies()gives before the publisher configuration has loaded, when the device reports no region. Once the configuration has loaded, the API decides.The iOS configuration has no theme option: the consent UI takes its colors from the theme configured in the Sirdata Console, in its light or dark version according to the system appearance (the light one when no dark version is configured). It has no certificate pinning option either.
Builder
The builder also has language(language:), which has no effect in 2.0.0.
SwiftUI — ConsentView
import SirDataCMPUI. The consent UI: banner, purposes and partners screens, and the US screen when US Privacy applies. Its initializer, as declared in SirDataCMPUI:
onFinish
Called when the user is done with the banner. Dismiss your presentation there.
initialScreen
Screen to open once the CMP is loaded, for example .purposes to open the preferences directly. nil (the default) opens the banner.
workflow
nil (the default) asks the display decision, so a partially answered consent opens in "apply choices" mode. Pass .manualDisplay when re-opening from a settings screen: the banner shows the close cross at the top and a "Reject all" button whatever the refusal type the publisher configured, restarts the cappingInDays window, and is reported as load:revisit.
Call
IosCMPApi.shared.notifyBannerShown()just before presenting it.ConsentViewfirescmpuicloseditself.Dismissing it without one of its buttons — swiping its sheet down, or pushing another view over it — records nothing: it is reported like the close button that saves nothing, and the banner comes back on the next launch.
Creating it before
initializeterminates the app in 2.0.0. The next release shows a message with a Close button instead.Known issue in 2.0.0: when the configuration could not be loaded at this launch (offline, for instance), it shows only a loading indicator, with no close control. A
.sheetcan still be swiped down; with.interactiveDismissDisabled()or in a full-screen presentation, nothing closes it. Present it in those two ways only whenIosCMPApi.shared.tcfApi().isCmpLoaded()istrue— see Setup. Fixed in the next release: a message and a Close button, and a Close button under the loading indicator after five seconds.
ConsentScreen
.main
The banner
.purposes
The purposes screen
.vendors
The partners screen
.purposeOne
The purpose 1 screen of the cookie wall
.mainMissing, .vendorsMissing
Not entry screens: values recorded in the TC string's consent screen field
Display decision
ConsentDisplayDecision has three properties: shouldDisplay: Bool, workflow: Workflow (pass it to ConsentView) and reason: DisplayReason.
Workflow
Description
.main
The standard banner. Also the workflow of every decision that does not display.
.applyChoices
Returned when the stored choice is missing only partners: the banner asks only about what is left to decide.
.cookiewall
Returned when the configuration enables the cookie wall and the stored choice does not grant purpose 1.
.cookiewallModify
Set by the consent UI itself when the user modifies their choices from the cookie wall. The decision never returns it.
.manualDisplay
Re-opening from a settings screen, passed by the app. The decision never returns it.
DisplayReason
shouldDisplay
Meaning
.gdprNotApplies
false
GDPR does not apply.
.consentRequired
true
Something is left to ask.
.cappingActive
false
A capping window is running on a stored choice that does not grant purpose 1.
.cappingAskLater
false
Nothing is stored, and "ask me later" was recorded less than an hour ago.
.consentOk
false
The stored choice needs nothing more, or a capping window is running on a choice that grants purpose 1.
.configNotLoaded
true or false
Provisional: the configuration had not loaded, so only GDPR applicability and the presence of a stored TC string were evaluated.
Shared Core Types
These types are shared with Android, and shown here in Kotlin, the language they are written in. Swift sees Int fields as Int32, Long as Int64, sets as Set<KotlinInt>, sealed-class cases as nested classes (ConsentResult.Success, ConsentResult.Error) and enum entries in lower camel case (ConsentState.ready, UserActionResponse.askLater).
ConsentResult
InitResult
ConsentState
ConsentData
CoreData
CustomData
PublisherTCData
UserActionResponse
ASK_LATER is reported to Sirdata as an "ask later" answer, but submitConsent still records the current selections, as for any other value. The consent UI never submits it: its "ask me later" button calls recordAskLater(), which records no consent.
SelectorStatus
Mis à jour
Ce contenu vous a-t-il été utile ?
