> For the complete documentation index, see [llms.txt](https://cmp.docs.sirdata.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cmp.docs.sirdata.net/applications-mobiles-sdk-natif/mobile-sdk/versions-1.md).

# iOS — Versions

> Cette page est maintenue en anglais — une seule source évite qu'une traduction dérive de la réalité du SDK à chaque release.

All notable changes to the iOS SDK. Entries are newest first.

Sections follow the same headings throughout: **Features** for new or changed behaviour, **Fixes** for corrections and, from 2.0.0, **Requirements** at the end. Breaking changes are called out in their own block at the top of the entry.

> Maintainers: a new entry is dated on the day the version is actually published, not when it is written. An entry marked `(unreleased)` has not been tagged yet — see the release checklist.

## Next release (unreleased)

**Fixes**

* **A call made before `initialize` no longer terminates the app.** The getters return a neutral value: `getConsentState()` a flow that stays `LOADING`, `getConsentUpdates()` a flow that stays at 0, `getConsentData()` an empty selection, `getGoogleConsentState()` every signal denied, `getLastTcStringError()` and `getLastForwardedConsentState()` `nil`, `getRegisteredAdapters()` an empty list, and `discardPendingChanges()` does nothing. `acceptAll()`, `rejectAll()`, `saveConsent()` and `submitConsent(userAction:)` throw a Swift error instead. Their Objective-C selectors are unchanged.
* **A second `initialize` without `shutdown()` is ignored and logged** (`[CMP]` line in the Xcode console), instead of terminating the app. The running session is kept.
* **`ConsentView` always offers a way out.** When the configuration could not be loaded at this launch (offline, unknown config ID), it shows a message and a Close button instead of a loading indicator that could not be closed in a full-screen presentation or with `.interactiveDismissDisabled()`. While the configuration loads, a Close button appears under the indicator after five seconds. Created before `initialize`, it shows the same message instead of terminating the app.
* **`getInitError()` is set when `getConsentState()` turns `READY`**, so it can be read as soon as `awaitConsentDisplayDecision()` returns, including in its completion handler. In 2.0.0 it could still be `nil` at that moment after a failed load.

## 2.0.0 (2026-10-05)

First version published on CocoaPods, as the pod `SirdataCMP`, alongside Swift Package Manager. The version number moves to 2.0.0 on every channel at once: the 1.x versions of that pod name are an older, discontinued Sirdata SDK.

**Breaking changes**

* **iOS 15.0 minimum, Swift Package Manager included** — the SPM package 1.2.0 declared iOS 14.0. Xcode 27 no longer builds a deployment target below 15.0.

**Features**

* **The consent adapters forward each choice to Firebase Analytics, AppsFlyer, Adjust and Branch**, from inside the SDK, through the Objective-C runtime. In 1.2.0 the forwarding was compiled out for every Swift Package Manager and CocoaPods integrator, only ran with the bundled UI, and called APIs these SDKs do not have. It now works with both package managers, with or without the bundled UI, and a failing adapter is logged in the Xcode console, prefixed with `[CMP]`. With Swift Package Manager, Firebase requires the `-ObjC` linker flag. See [Sharing consent with vendor SDKs](/applications-mobiles-sdk-natif/mobile-sdk/sharing-consent.md).
* **"TCF/Google Consent Mode Interoperability" (`consentModeFromTcf`) behaves as on the web.** The SDK writes `IABTCF_EnableAdvertiserConsentMode` = 1, `ping` and `getTCData` carry `enableAdvertiserConsentMode: true`, and Firebase Analytics receives `analytics_storage` only, so that it derives the three ad signals from the TC string.
* **Publisher restrictions are applied.** The consent UI no longer asks a partner for a purpose the publisher forbids it, the TC string and the `IABTCF_PublisherRestrictions{ID}` keys carry the restrictions, and the signals sent to Google through Firebase and AppsFlyer take them into account.
* The Sirdata consent string carries the restrictions the configuration applies to Sirdata partners, and the version of the Sirdata list it was built from (it always said 1).
* The three non-versioned lists (Global Vendor List, Sirdata list, Google Additional Consent providers) are requested with the visitor's country, when it is known, so the API can filter them.
* The consent archive carries the country and the revision of the configuration that was displayed. Every hit carries a `page_view_id`, drawn once per `initialize()`, so the load, the clicks and the answer of one display share it.
* **The banner's refusal button follows the publisher's style as the web does.** "Close link" puts the refusal label in the header, in place of the close cross (it was a grey cross without a label, on its own line); "Big button (secondary color)" is outlined like "Customize my choices" (it was a solid grey block); "Big button (main color)" looks exactly like "Accept all" (it was drawn at 70 % opacity). The manual re-opening shows a "Reject all" button whatever the refusal type and style, with the close cross at the top; it showed no refusal at all.
* The purposes and partners screens carry the links of their scope reminder, as on the web: the list of the sites the consent covers, and the Consent Framework site.
* Outside the US screen, the close button that saves nothing reports its answer, `response:close`, along with its click, `ui:close`, as the web does; 1.2.0 sent the click alone. The US screen's close button still reports `ccpa_response:close` alone. Under the CNIL variant, where the close button saves the choice, nothing changes.
* Dismissing the consent sheet by swiping it down is reported like the close button that saves nothing (`response:close` and `ui:close`, or `ccpa_response:close` on the US screen), and fires `cmpuiclosed`. Any removal of `ConsentView` from the screen that does not go through one of its buttons counts as such a dismissal — a view pushed over it, for instance.
* `isGdprApplies()` and the in-app TCF API return `context.gdprApplies` as served by the API; the SDK no longer adds `forceGdpr` on top of it. The server already folds `forceGdpr` into that value, so what an integrator sees does not change.

**Fixes**

* **The SDK no longer fails to start on a configuration that serves publisher restrictions.** The API serves `restrictionType` as a number, which 1.2.0 could not decode: `initialize()` failed and the CMP never loaded.
* **The publisher's text size is applied.** It was computed and never read. It now shifts Dynamic Type by one step down ("small") or up ("large"), so the system's accessibility text size keeps working.
* Toggling a stack records only the members the screen shows, and a purpose row records only the legal bases the served list asks for. Both could record a consent or a legitimate interest the user was never asked for.
* `Utils.buildAddtlConsent(customData:)` returns the string the SDK stores in `IABTCF_AddtlConsent`, prefixed `2~`. It returned a `1~` string that no device ever stored.
* In dark mode, a logo or watermark set to "no image" no longer displays the word `NONE`, and an empty dark-mode image falls back to the light-mode one, as on the web.
* A long refusal label ("Continuer sans accepter") wraps onto two lines instead of being truncated, and a banner shown at the bottom of the screen extends its background under the home indicator.

**Requirements**

* iOS 15.0 or later, whatever the channel; Swift 5.9 or later (Xcode 15 or later); verified with Xcode 27.0. See [Setup — iOS](/applications-mobiles-sdk-natif/mobile-sdk/setup-1.md), step 1.

## 1.2.0 (2026-09-23)

First version distributed through a package channel other than a raw git tag: Swift Package Manager resolves it from an XCFramework attached to the GitHub release, verified by its SHA-256 checksum. The pod announced for this version was never published: the CocoaPods trunk refused it, because pod names are case-insensitive and `SirdataCMP`, an older Sirdata SDK, already holds the name. The channel opens with 2.0.0, under that name.

**Breaking changes**

* The `setGdprApplies` command is removed from the in-app TCF API. It duplicated `forceGdpr`, which stays the single supported way to override GDPR applicability. Callers using `setGdprApplies` must switch to `forceGdpr`.
* Two public symbols are removed from the Kotlin framework: `TcStringEncoder.convertTcStringToGppString(tcString:)` and `Context.isAskLaterCappingActive(store:)`. Neither has ever been reachable from a published artifact, and both were dead in the SDK itself: the first built a GPP string carrying the TCF section alone, which stopped being the production path when the US National section arrived (the string and `IABGPP_GppSID` are now assembled together from one section list); the second duplicated the "ask later" capping rule with a *different* window — `context.cappingInHours` instead of the fixed one hour. Read `IABGPP_HDR_GppString` for the GPP string, and call `awaitConsentDisplayDecision()` to ask whether the banner should be shown.

**Features**

* **The main-thread contract of `initialize`, `shutdown` and `setCcpaOptOut` is enforced rather than only documented.** The three read and re-encode the consent state — jurisdiction, configuration and store — together and without a lock, so calling them from a background thread is a race. Off the main thread the SDK now logs the violation, naming the entry point; declare `debugMode(true)` on the configuration and it throws instead, so the fault surfaces in your own debug build rather than as a rare, silent race in production. `debugMode` has no other effect.
* **The SDK's language coverage goes from 18 to 50** — every locale the Sirdata API serves. A device set to one of the 32 missing languages previously fell back to the partner's default language, because `getDeviceLanguage()` could not represent it. BCP 47 tags are now matched with their full label and case-insensitively, the way `NSLocale.preferredLanguages` actually reports them.
* **Right-to-left languages render right-to-left.** The consent UI had no layout direction handling at all and inherited the host app's reading direction: an Arabic app displaying a French banner mirrored it, and a French app displaying an Arabic banner did not. The UI now sets its own direction from the banner's language — LTR as explicitly as RTL, which is what closes the inheritance for the 48 left-to-right languages.
* Norwegian and Filipino are reachable: devices report `nb-NO`, `nn-NO` or `fil-PH`, none of which matched the `no` / `tl` codes the API serves. An alias table maps them; the failure was silent — no error, no log, just a banner in the wrong language.
* The consent UI no longer lists a partner for which the user has no decision to make — a partner with neither a consent nor a legitimate-interest toggle was previously rendered as an inert row.
* Version alignment: the SDK, the pod and the React Native bridge now declare and resolve the same version. Earlier numbering diverged across the podspec and the Gradle module.
* **GPP US National (section 7)** is emitted alongside the deprecated `uspv1` section, and `IABGPP_GppSID` is built from the same section list as the string rather than derived from it — it used to be read back out of a Fibonacci-encoded header, which cannot work, so it never announced anything but `2`.
* **The publisher configuration is now fetched from the `cacheApiRoot` host** (`choices.consentframework.com` by default) rather than `apiRoot` (`api.consentframework.com`). Both hosts serve the same endpoint, and the two responses were compared key by key: 614 keys against 615, no differing value, the single extra key being the `context.region` that only `choices` can carry — it sits behind the CDN that resolves the visitor's country and US state, which the US National section needs. Integrators who pin hosts in a network allowlist, a proxy rule or a certificate-pinning configuration should confirm `cacheApiRoot` is reachable — the other two hosts are unchanged, and all three remain configurable.
* `getUspString()` returns an empty string when no opt-out decision has been recorded. `"1---"` is not a neutral default: the US Privacy spec makes it an explicit assertion that the consumer falls outside a US Privacy jurisdiction. The sale opt-out itself is recorded under its own key, so a value fabricated by an earlier SDK version can never be mistaken for a decision the user made.

**Fixes**

* `ping` no longer reports a GDPR determination it has not actually made. Until the publisher configuration is loaded, the command reports the undetermined state instead of a default that could be wrong, so vendor SDKs stop acting on a value the CMP had not computed.
* **`getGdprApplies()` no longer asserts that GDPR does not apply when the key is absent.** On a fresh install, or after `clearConsent()`, `NSUserDefaults` returns `0` for a missing key exactly as for a stored zero — and `0` is not "undetermined", it is the firm claim that GDPR does **not** apply, which a vendor acts on without consent. Absence is now distinguished from a stored value, matching Android. This affected `getTCData` and the GPP `tcfeuv2` section.
* **`clearConsent()` also removes the legacy `IABTCF_*` key names.** They were still read as a fallback, so consent that had been cleared came back on the next launch.
* The TCF policy version fallback lives in the storage reader rather than at each call site, so `ping` and `getTCData` can no longer report different values in the same session.
* In the "apply choices" workflow, the refusal button is no longer rendered when the publisher set the no-consent button to `NONE` — that is, when they explicitly chose not to offer a refusal on the banner.

## 1.1.0 (2026-08-10)

Tagged in Sirdata's private source repository only: never resolvable from the public package repository, never published to the CocoaPods trunk, and not announced as generally available.

**Features**

* IAB TCF v2.2 in-app CMP API (registered CMP ID 92), IAB GPP and CCPA/USP support, with all signals written to `NSUserDefaults` under the standard IAB keys.
* Native SwiftUI consent UI (`ConsentView`): banner, purposes and partners screens, themed from the publisher configuration.
* Display cascade ported from the web CMP — `awaitConsentDisplayDecision()` decides whether and how to present the UI, covering partial consent, capping windows and the cookie wall.
* `MANUAL_DISPLAY` and `APPLY_CHOICES` workflows for re-opening the UI from a settings screen and for asking only what is left to decide.
* Google Additional Consent string and Google Consent Mode state derived from TCF purposes.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://cmp.docs.sirdata.net/applications-mobiles-sdk-natif/mobile-sdk/versions-1.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
