Skip to content

feat(ios): support moving kits from CocoaPods to Swift Package Manager - #147

Open
thomson-t wants to merge 3 commits into
mainfrom
feat/ios-kits-swift-package-manager
Open

thomson-t wants to merge 3 commits into
mainfrom
feat/ios-kits-swift-package-manager

Conversation

@thomson-t

Copy link
Copy Markdown
Contributor

Why

Flutter apps built with Flutter 3.44 or later get their iOS libraries through Swift Package Manager by default, and the CocoaPods registry stops accepting new library versions on 2 December 2026, so apps using this plugin are moving off CocoaPods now. The plugin already builds with Swift Package Manager, but our setup guide still tells apps to add the mParticle and Rokt libraries through CocoaPods. An app that follows the guide on a current Flutter version ends up with two copies of the mParticle SDK: it builds and launches, but integrations such as Rokt attach to one copy while the app talks to the other. Once this lands, the guide explains the Swift Package Manager setup, the plugin warns when an app contains two copies, and iOS reports a missing Rokt integration the same way Android already does.

Programme

Part of moving the mParticle SDKs off CocoaPods before the CocoaPods registry becomes read-only on 2 December 2026, as announced on the CocoaPods blog. There is no ticket; an SDK engineer requested the work. The React Native SDK made the same move in mParticle/react-native-mparticle#436.

What changes

Before: the README's iOS steps covered only CocoaPods and never mentioned the iOS Rokt kit. In the Swift Package Manager CI job, the example app took the plugin from Swift Package Manager and the kits from CocoaPods, so it built an app with two copies of the SDK and passed. iOS Rokt calls reported success when the Rokt kit was missing.

After:

  • Duplicate warning. At launch the plugin logs [mParticle] The mParticle SDK is loaded more than once (…) when the SDK or Rokt classes are linked into more than one binary of the app.
  • Missing Rokt kit. The four iOS Rokt methods return a PlatformException ("Rokt is unavailable. Add the mParticle Rokt kit (mParticle-Rokt) to your iOS app.") instead of reporting success, as Android does.
  • One version source. The podspec reads the minimum mParticle Apple SDK version from Package.swift (now >= 9.3.1, < 10.0; it was ~> 9.3), and Package.swift uses the same package URL as the mParticle kits.
  • Example app and CI. The example uses Swift Package Manager only. Both iOS CI jobs fail if the Release app links any of the SDK's key classes more than once.
  • Docs. README, MIGRATING.md and CHANGELOG cover Swift Package Manager setup, kits, the move from CocoaPods, and troubleshooting.

Start with MparticleFlutterSdkPlugin.swift, which holds both behaviour changes, then .github/workflows/build-ios.yml, then the README iOS section. Check first whether the missing-kit error is acceptable in a minor release. Deliberately left alone:

  • The Flutter version floor stays at >=3.10.0. The README says Swift Package Manager needs Flutter 3.41 or later.
  • Package.resolved is not committed, so CI builds the newest versions within the declared ranges.

Linked work

Related: mParticle/react-native-mparticle#436, the same move for the React Native SDK.

Rollout

Path: ships in the next plugin release from main on pub.dev. Apps get it when they upgrade; nothing changes for app versions already released.
Feature flags: none.
Turning it off: before the release, revert this pull request. After it, a published version cannot be recalled; a fix ships in the next release, and apps can stay on 2.2.1 until then.
What we watch: there is no dashboard. After the release, we read issues on this repository and support reports for "Rokt is unavailable" or "loaded more than once". A report of the Rokt error from an app that does include the Rokt kit would mean the check is wrong and needs a patch release.

Risks

  • iOS apps that call Rokt APIs without the Rokt kit now get an error instead of silent success, and an unawaited call shows up as an unhandled asynchronous error; this matches Android and is listed under Changed in the CHANGELOG; we would see PlatformException(MparticleFlutterSdkPlugin, Rokt is unavailable…) in app logs or crash reports.
  • The kit check looks for the Rokt kit's MPKitRokt class, so a rename in the kit would make it misfire; the class was present in both the CocoaPods and Swift Package Manager builds checked locally; we would see the Rokt error from an app that includes the kit.
  • The duplicate scan runs once at every launch, Release builds included; it reads only the class names of binaries inside the app bundle, but it was not timed; we would see it in launch profiling.
  • The podspec now parses Package.swift, so reformatting that dependency line breaks pod install; the podspec stops with a clear error, a comment beside the line says so, and the CocoaPods CI job builds through the podspec; we would see a failing CocoaPods job.
  • The core package URL in Package.swift drops .git; Swift Package Manager treats both forms as the same package, which a local resolve confirmed; we would see package resolution errors in apps or CI.
  • Contributors who built the example with CocoaPods now need Swift Package Manager, and the CocoaPods CI job edits the example's Xcode project inside the run; the README documents the setup; we would see a failing CocoaPods job or hear from contributors.

Risk class: higher — iOS apps that call Rokt APIs without the Rokt kit start receiving errors after they upgrade.

Who

Written by: an automated coding agent (Claude Code), at the request of an SDK engineer, following a migration plan agreed with that engineer (not published).
Code reviewed before opening: an automated review agent reviewed the staged change twice before commit. Three of its suggestions were applied: an explicit list of Rokt methods, a note in Package.swift, and one removed comment. No person has reviewed it yet.
Design reviewed before opening: the requesting SDK engineer approved the plan and its scope on 20 October 2026; no one else.
Decision this implements: the requesting SDK engineer's decisions of 20 October 2026, with no public record: keep CocoaPods support alongside Swift Package Manager, keep the Flutter version floor, and return an error on iOS when the Rokt kit is missing.
Checked: on 20 and 21 October 2026, locally with Flutter 3.47.7 and Xcode 27. Release device builds of the example in both modes pass the single-copy check. The setup before this change fails it in a Debug simulator build, shows 274 duplicate-class warnings at launch, and triggers the new warning. A build without the Rokt kit returns the new error at launch. flutter test passes for the plugin and the example, pod ipc spec gives the new version range, and flutter pub publish --dry-run shows no files from .github/ in the package.
Not checked: the GitHub Actions jobs (Xcode 16.4 on macOS 15), which first run on this pull request. A live Rokt placement, which needs a real key and network access. Flutter versions other than 3.47.7, including the 3.41 minimum the README states, which comes from Flutter's documentation and source. The iOS 27 simulator, where the example already crashes at launch because it has not adopted the UIScene lifecycle; that is unrelated to this change.

Size

Hand-written: about 275 lines across 12 files, including the deleted 49-line Podfile.
Generated: 3 files.

Notes for reviewers

Generated files:

  • example/ios/Runner.xcodeproj/project.pbxproj: Flutter 3.47.7's Swift Package Manager migration, pod deintegrate, and the xcodeproj Ruby gem, which added the two kit package references and removed the empty Pods group.
  • example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: Flutter's Swift Package Manager migration, which adds its prepare-framework pre-action.
  • example/ios/Runner/AppDelegate.swift: the Flutter tool's @UIApplicationMain to @main migration.

Single-copy check on the example, Debug simulator build:

before (plugin from Swift Package Manager, kits from CocoaPods)
MParticle: 2 [Runner.debug.dylib mParticle_Apple_SDK_ObjC]
RoktEmbeddedView: 2 [Runner.debug.dylib RoktContracts]
MPKitRokt: 1 [mParticle_Rokt]

after (Swift Package Manager only)
MParticle: 1 [Runner.debug.dylib]
RoktEmbeddedView: 1 [Runner.debug.dylib]
MPKitRokt: 1 [Runner.debug.dylib]

CI details:

  • The Swift Package Manager job keeps its mparticle_flutter_sdk checkout path. A path dependency still fails on Flutter 3.47.7 when the folder name differs from the package name (flutter/flutter#186881, closed upstream).
  • Flutter's migration adds the plugin's own folder to the example's Xcode project. With Swift Package Manager off, Xcode still resolves that folder and fails on ../FlutterFramework, so the CocoaPods job removes the reference. Only the plugin's example has it; apps do not.
  • The first local package resolve failed with no versions of 'rokt-payment-extension-ios' match the requirement because of a stale Swift Package Manager cache, and passed after a refresh. The README troubleshooting entry covers it.

Flutter 3.44 and later build iOS plugins with Swift Package Manager by
default, and CocoaPods trunk becomes read-only on 2 December 2026. When
an app keeps mParticle or Rokt pods in its Podfile while the plugin
comes from Swift Package Manager, the app links two copies of the SDK
and kits register with the wrong one. The build still succeeds.

- Log a warning at launch when the SDK is linked more than once.
- Return an error from iOS Rokt calls when the Rokt kit is missing, as
  Android already does.
- Read the podspec's core SDK version from Package.swift, and use the
  same mparticle-apple-sdk package URL as the kits.
- Move the example app to Swift Package Manager, and check in CI for
  both dependency managers that each SDK class is linked once.
- Document Swift Package Manager setup, kits and the migration.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings marked 🟡 are optional suggestions and need no follow-up push.

Comment thread .github/workflows/build-ios.yml Outdated
Flutter releases before 3.24 never generate the
FlutterGeneratedPluginSwiftPackage that the example project now
references, so the CocoaPods job could not resolve packages on them.
Remove every Swift package link and reference instead of only the
remote ones, so the example builds as a plain CocoaPods app on any
Flutter version.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@nickolas-dimitrakas nickolas-dimitrakas left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Read through the diff and the existing review threads; no blocking issues. The missing-kit error matches Android. Optional follow-up: catch the PlatformException in Rokt.events() so unawaited calls don't surface as unhandled errors. Note the iOS build jobs were still queued when I reviewed, so please confirm they pass before merging.

Flutter's Swift Package Manager migration added the plugin's own folder
to the example's Xcode project. Xcode treats that folder as a local
override of the plugin package and names it after the folder, while
Flutter names the same package after the checkout folder. In a checkout
not named mparticle_flutter_sdk, including a default clone, package
resolution failed with an identity mismatch.

Remove that reference, and let the Swift Package Manager CI job use the
default checkout folder so that it covers a normal clone.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants