Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b3d30e8
Create Package.swift file for spm support
reshab-code May 7, 2026
2a7a415
Create symlinks for spm
reshab-code May 7, 2026
5d96862
Add guard to obj c imports in ClevertapPlugin.m
reshab-code May 7, 2026
203c1e3
wrapped both CTJsonTemplateProducer.h and CTCustomTemplatesManager.h …
reshab-code May 7, 2026
b91d176
Narrowed header files in podspec
reshab-code May 7, 2026
c0b7ecf
Relocate Package.swift to ios/clevertap_plugin/ for Flutter SPM detec…
reshab-code May 8, 2026
dfd2cf9
Add swift package name under ios in pubspec.yaml, added guards for th…
reshab-code May 19, 2026
52d2d8e
Fix Package.swift to use same version as podspec to ensure no drift
reshab-code Jun 23, 2026
a7c16ee
Restructure folders and files as per the official flutter docs
reshab-code Jun 23, 2026
8751ec8
Merge branch 'develop' into task/SDK-5694-spm-support-flutter-sdk
reshab-code Jun 25, 2026
9e9fdf6
Fix version in package.swift to match podspec for correct version res…
reshab-code Jun 25, 2026
74ecaa9
Add spm integration doc for flutter
reshab-code Jun 25, 2026
c22b0dc
Fix flutter version in pubspec to 1.1.7 and enable spm for supported …
reshab-code Jun 30, 2026
8230f92
correct and trim the ios spm integration doc, fixing the enabling ste…
akashvercetti Aug 4, 2026
8922ed1
ignore flutter ephemeral, local claude settings, and generated sdk re…
akashvercetti Aug 4, 2026
7fa5ea4
Fix pr comments and add flutter framework dependency for swift pm rou…
reshab-code Aug 15, 2026
25a953a
update integration doc for ct plugin v4.2.0 and core ios sdk verison …
reshab-code Aug 20, 2026
c021559
merge feat/release_4.2.0, resolve usnotifications import conflict in …
reshab-code Aug 23, 2026
da297b1
remove publicHeadersPath from Package.swift after docs review
reshab-code Aug 26, 2026
d6b8acb
port getAppLaunchNotification implementation to spm source path.
reshab-code Aug 26, 2026
6589ae0
merge feat/release_4.2.0, bring in getAppLaunchNotification ios fix a…
reshab-code Aug 26, 2026
5dd7d9f
remove flutterframework dependency from package.swift to support lowe…
reshab-code Aug 27, 2026
d65e9ac
add flutterframework warning to ios spm troubleshooting docs.
reshab-code Aug 27, 2026
46f7bbf
port dismissPipInApp to spm source path.
reshab-code Sep 1, 2026
b423822
merge feat/release_4.2.0, resolve ios/Classes modify/delete conflict.
reshab-code Sep 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,9 @@ example/pubspec.lock
pubspec.lock
example/android/app/property*

# Local Claude Code settings
.claude/settings.local.json

# Generated SDK review reports
sdk-review-*.html

124 changes: 124 additions & 0 deletions doc/Integrate-iOS-SPM.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
## 📦 iOS Integration via Swift Package Manager (SPM)

Flutter introduced Swift Package Manager support as an **opt-in** feature in Flutter 3.24, and it became the **default** package manager in Flutter 3.44. The CleverTap Flutter plugin ships a `Package.swift` alongside its podspec, so both package managers resolve the same native SDK version (`CleverTap-iOS-SDK 7.7.1`).
Comment thread
reshab-code marked this conversation as resolved.
Outdated
Comment thread
reshab-code marked this conversation as resolved.
Outdated

> **Minimum requirements for SPM integration**
> - Flutter 3.24+ (opt-in) - enabled by default from Flutter 3.44
Comment thread
reshab-code marked this conversation as resolved.
> - Xcode 15+ (required for `swift-tools-version: 5.9`)
> - iOS deployment target: 13.0+
>
> If you are on Flutter < 3.24, the plugin continues to work via CocoaPods - no action required.

---

### How it works

The plugin ships a Swift package that pins `CleverTap-iOS-SDK 7.7.1`. When your app is built with SPM enabled, Flutter resolves it automatically - you don't add anything to your app's own `Package.swift` or edit any plugin files.

---

### Enabling SPM in your Flutter app

SPM is opt-in on Flutter 3.24–3.43 (and on by default from 3.44). There is **no** `flutter run`/`flutter build` flag and **no** `Info.plist` key for this - you enable it through Flutter configuration.

**Per project (recommended for testing)** - add to your app's `pubspec.yaml`:

```yaml
flutter:
config:
enable-swift-package-manager: true
```

**Globally for your machine:**

```bash
flutter config --enable-swift-package-manager
```

To turn it back off, use `enable-swift-package-manager: false` in `pubspec.yaml`, or `flutter config --no-enable-swift-package-manager` globally.

---

### Migrating an existing CocoaPods app to SPM

Once SPM is enabled, Flutter migrates the Xcode project automatically the next time you build or run. To migrate cleanly on an app that already uses CocoaPods:

**1. Enable SPM** (per-project block above, or global flag).

**2. Clear the existing CocoaPods state** (run from your app root):

```bash
flutter clean
cd ios
rm -rf Pods Podfile.lock .symlinks build
rm -rf ~/Library/Developer/Xcode/DerivedData/Runner-*
cd ..
```

**3. Re-resolve and trigger the migration:**

```bash
flutter pub get
flutter build ios --config-only # or: flutter run
```

On this build Flutter adds a `FlutterGeneratedPluginSwiftPackage` to the Xcode project and resolves every plugin that ships a `Package.swift` (including `clevertap_plugin`) via SPM. Plugins that only ship a podspec stay on CocoaPods - a hybrid setup is expected.

**4. Verify SPM took over.** Open `ios/Runner.xcworkspace` and confirm:
- **Package Dependencies** lists `clevertap_plugin` and, transitively, `clevertap-ios-sdk` at `7.7.1`.
- The regenerated `Podfile.lock` no longer contains a `clevertap_plugin` pod entry.

**5. Build and run** on a simulator/device and smoke-test CleverTap initialization plus a `recordEvent` to confirm native symbols link.

---

### AppDelegate changes when using SPM

When Flutter resolves the plugin via SPM, the module name changes. Use conditional imports in your `AppDelegate` to support both CocoaPods and SPM builds:

**Objective-C**

```objc
#if __has_include(<CleverTapSDK/CleverTap.h>)
#import <CleverTapSDK/CleverTap.h>
#else
#import "CleverTap.h"
#endif

#if __has_include(<clevertap_plugin/CleverTapPlugin.h>)
#import <clevertap_plugin/CleverTapPlugin.h>
#else
#import "CleverTapPlugin.h"
#endif
```

**Swift**

```swift
import CleverTapSDK
import clevertap_plugin
```

These guards ensure your app compiles correctly regardless of which package manager resolved the dependency.

---

### CocoaPods vs SPM

| | CocoaPods | SPM |
|---|---|---|
| SDK version pinned | `7.7.1` | `7.7.1` |
| Deployment target | `13.0` | `13.0` |
Comment thread
reshab-code marked this conversation as resolved.
Outdated
| Opt-in required | No | Yes on Flutter 3.24–3.43; default from 3.44 |

Both package managers resolve the same CleverTap iOS SDK version to ensure no drift between the two integration paths.

---

### Troubleshooting

- **Xcode doesn't resolve the package**: Run `flutter pub get`, then in Xcode go to **File → Packages → Resolve Package Versions**.
- **Automatic migration didn't add the package**: In Xcode, add it manually - **Package Dependencies → Add Local…** → select `ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage` and add it to the `Runner` target. Then under **Product → Scheme → Edit Scheme → Build → Pre-actions**, add a Run Script (with build settings from `Runner`): `"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" prepare`.
Comment thread
reshab-code marked this conversation as resolved.
- **Duplicate symbol errors**: Don't use both CocoaPods and SPM for the same plugin at once. If a `Podfile` exists and SPM is enabled, Flutter prefers SPM for plugins that support it.
- **Build fails with missing headers**: Verify your deployment target is `13.0` or higher in both your Xcode project and `Podfile`/`Package.swift`.
Comment thread
reshab-code marked this conversation as resolved.
- **Stale CocoaPods references after migrating**: If the build still runs `[CP]` Pods build phases (or duplicate-embeds a framework) for a plugin that has moved to SPM, run `pod deintegrate` in your app's `ios/` directory, then `flutter clean && flutter build ios` so Flutter re-integrates cleanly. Use this only as a recovery step - it is not part of the normal migration flow. Flutter regenerates the CocoaPods integration on every build, so a manual `pod deintegrate` is otherwise undone on the next build.
1 change: 1 addition & 0 deletions example/ios/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
Flutter/ephemeral/
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*

Expand Down
9 changes: 9 additions & 0 deletions example/ios/Runner/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,18 @@
#import "GeneratedPluginRegistrant.h"
#import <UserNotifications/UserNotifications.h>

#if __has_include(<CleverTapSDK/CleverTap.h>)
#import <CleverTapSDK/CleverTap.h>
#else
#import "CleverTap.h"
#endif
#if __has_include(<clevertap_plugin/CleverTapPlugin.h>)
#import <clevertap_plugin/CleverTapPlugin.h>
#import <clevertap_plugin/CleverTapPluginCustomTemplates.h>
#else
#import "CleverTapPlugin.h"
#import "CleverTapPluginCustomTemplates.h"
#endif

@implementation AppDelegate

Expand Down
4 changes: 3 additions & 1 deletion ios/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ Icon?
.tags*

/Flutter/Generated.xcconfig
/Flutter/flutter_export_environment.sh
/Flutter/flutter_export_environment.sh

.swiftpm/
6 changes: 3 additions & 3 deletions ios/clevertap_plugin.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ Pod::Spec.new do |s|
s.license = { :file => '../LICENSE' }
s.author = { "CleverTap" => "http://www.clevertap.com" }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.source_files = 'clevertap_plugin/Sources/clevertap_plugin/**/*.{h,m}'
s.public_header_files = 'clevertap_plugin/Sources/clevertap_plugin/include/clevertap_plugin/*.h'
s.dependency 'Flutter'
s.dependency 'CleverTap-iOS-SDK', '7.7.1'
s.ios.deployment_target = '9.0'
s.ios.deployment_target = '13.0'
Comment thread
reshab-code marked this conversation as resolved.
Outdated
end

30 changes: 30 additions & 0 deletions ios/clevertap_plugin/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// swift-tools-version: 5.9
import PackageDescription

let package = Package(
name: "clevertap_plugin",
platforms: [
.iOS("13.0")
],
products: [
.library(name: "clevertap-plugin", targets: ["clevertap_plugin"])
],
dependencies: [
.package(
url: "https://github.com/CleverTap/clevertap-ios-sdk",
exact: "7.7.1"
Comment thread
reshab-code marked this conversation as resolved.
Outdated
)
],
targets: [
.target(
name: "clevertap_plugin",
dependencies: [
.product(name: "CleverTapSDK", package: "clevertap-ios-sdk")
],
publicHeadersPath: "include/clevertap_plugin",
Comment thread
reshab-code marked this conversation as resolved.
Outdated
Comment thread
reshab-code marked this conversation as resolved.
Outdated
cSettings: [
.headerSearchPath("include/clevertap_plugin")
]
)
]
)
Original file line number Diff line number Diff line change
@@ -1,21 +1,101 @@

#if __has_include(<CleverTapSDK/CleverTap.h>)
#import <CleverTapSDK/CleverTap.h>
#else
#import "CleverTap.h"
#endif

#import "CleverTapPlugin.h"

#if __has_include(<CleverTapSDK/CleverTap+Inbox.h>)
#import <CleverTapSDK/CleverTap+Inbox.h>
#else
#import "CleverTap+Inbox.h"
#endif

#if __has_include(<CleverTapSDK/CleverTapUTMDetail.h>)
#import <CleverTapSDK/CleverTapUTMDetail.h>
#else
#import "CleverTapUTMDetail.h"
#endif

#if __has_include(<CleverTapSDK/CleverTapEventDetail.h>)
#import <CleverTapSDK/CleverTapEventDetail.h>
#else
#import "CleverTapEventDetail.h"
#endif

#if __has_include(<CleverTapSDK/CleverTapSyncDelegate.h>)
#import <CleverTapSDK/CleverTapSyncDelegate.h>
#else
#import "CleverTapSyncDelegate.h"
#endif

#if __has_include(<CleverTapSDK/CleverTap+DisplayUnit.h>)
#import <CleverTapSDK/CleverTap+DisplayUnit.h>
#else
#import "CleverTap+DisplayUnit.h"
#endif

#if __has_include(<CleverTapSDK/CleverTap+FeatureFlags.h>)
#import <CleverTapSDK/CleverTap+FeatureFlags.h>
#else
#import "CleverTap+FeatureFlags.h"
#endif

#if __has_include(<CleverTapSDK/CleverTap+ProductConfig.h>)
#import <CleverTapSDK/CleverTap+ProductConfig.h>
#else
#import "CleverTap+ProductConfig.h"
#endif

#if __has_include(<CleverTapSDK/CleverTapPushNotificationDelegate.h>)
#import <CleverTapSDK/CleverTapPushNotificationDelegate.h>
#else
#import "CleverTapPushNotificationDelegate.h"
#endif

#if __has_include(<CleverTapSDK/CleverTapInAppNotificationDelegate.h>)
#import <CleverTapSDK/CleverTapInAppNotificationDelegate.h>
#else
#import "CleverTapInAppNotificationDelegate.h"
#endif

#if __has_include(<CleverTapSDK/CleverTap+InAppNotifications.h>)
#import <CleverTapSDK/CleverTap+InAppNotifications.h>
#else
#import "CleverTap+InAppNotifications.h"
#endif

#if __has_include(<CleverTapSDK/CleverTap+PushPermission.h>)
#import <CleverTapSDK/CleverTap+PushPermission.h>
#else
#import "CleverTap+PushPermission.h"
#endif

#if __has_include(<CleverTapSDK/CTLocalInApp.h>)
#import <CleverTapSDK/CTLocalInApp.h>
#else
#import "CTLocalInApp.h"
#endif

#if __has_include(<CleverTapSDK/CleverTap+CTVar.h>)
#import <CleverTapSDK/CleverTap+CTVar.h>
#else
#import "CleverTap+CTVar.h"
#endif

#if __has_include(<CleverTapSDK/CTVar.h>)
#import <CleverTapSDK/CTVar.h>
#else
#import "CTVar.h"
#endif

#if __has_include(<CleverTapSDK/CTTemplateContext.h>)
#import <CleverTapSDK/CTTemplateContext.h>
#else
#import "CTTemplateContext.h"
#endif

@interface CleverTapPlugin () <CleverTapSyncDelegate, CleverTapInAppNotificationDelegate, CleverTapDisplayUnitDelegate, CleverTapInboxViewControllerDelegate, CleverTapProductConfigDelegate, CleverTapFeatureFlagsDelegate, CleverTapPushNotificationDelegate, CleverTapPushPermissionDelegate>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,18 @@
#import "CleverTapPluginCustomTemplates.h"
#import "CleverTapPluginTemplatePresenter.h"
#import "CleverTapPluginAppFunctionPresenter.h"

#if __has_include(<CleverTapSDK/CTJsonTemplateProducer.h>)
#import <CleverTapSDK/CTJsonTemplateProducer.h>
#else
#import "CTJsonTemplateProducer.h"
#endif

#if __has_include(<CleverTapSDK/CTCustomTemplatesManager.h>)
#import <CleverTapSDK/CTCustomTemplatesManager.h>
#else
#import "CTCustomTemplatesManager.h"
#endif

@implementation CleverTapPluginCustomTemplates

Expand Down
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ flutter:
pluginClass: CleverTapPlugin
ios:
pluginClass: CleverTapPlugin
swiftPackageName: clevertap_plugin
web:
pluginClass: CleverTapPluginWeb
fileName: clevertap_plugin_web.dart