diff --git a/doc/Integrate-iOS-SPM.md b/doc/Integrate-iOS-SPM.md new file mode 100644 index 00000000..731b144a --- /dev/null +++ b/doc/Integrate-iOS-SPM.md @@ -0,0 +1,104 @@ +## 📦 iOS Integration via Swift Package Manager (SPM) + +Starting from Flutter 3.27, Flutter supports resolving plugin dependencies via Swift Package Manager in addition to CocoaPods. 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`). + +> **Minimum requirements** +> - Flutter 3.27+ +> - Xcode 15+ +> - iOS deployment target: 13.0+ + +--- + +### How it works + +Flutter's SPM support detects plugins that declare a `swiftPackageName` in their `pubspec.yaml`. The CleverTap plugin sets: + +```yaml +# pubspec.yaml (inside the plugin) +ios: + pluginClass: CleverTapPlugin + swiftPackageName: clevertap_plugin +``` + +Flutter then looks for a `Package.swift` under `ios//` (`ios/clevertap_plugin/Package.swift`). That manifest pins the CleverTap iOS SDK: + +```swift +.package( + url: "https://github.com/CleverTap/clevertap-ios-sdk", + exact: "7.7.1" +) +``` + +When your app is built, Flutter resolves this package automatically — no manual entry in `Package.swift` of your app is required. + +--- + +### Enabling SPM in your Flutter app + +SPM support in Flutter is opt-in. Enable it by setting the `FLTEnableSwiftPackageManagerIntegration` flag in your iOS app's `Info.plist`: + +```xml +FLTEnableSwiftPackageManagerIntegration + +``` + +Or via the Flutter CLI environment variable when running or building: + +```bash +flutter run --enable-swift-package-manager +flutter build ios --enable-swift-package-manager +``` + +After enabling, run `flutter pub get` and then open your `.xcworkspace` in Xcode. Xcode will resolve the CleverTap iOS SDK via SPM automatically. + +--- + +### 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() +#import +#else +#import "CleverTap.h" +#endif + +#if __has_include() +#import +#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 | +|---|---|---| +| Config file | `ios/clevertap_plugin.podspec` | `ios/clevertap_plugin/Package.swift` | +| SDK version pinned | `7.7.1` | `7.7.1` | +| Deployment target | `13.0` | `13.0` | +| Opt-in required | No (default) | Yes (see above) | + +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**. +- **Duplicate symbol errors**: Ensure you are not using both CocoaPods and SPM for the same plugin simultaneously. If you have a `Podfile` and SPM enabled, Flutter will prefer SPM for plugins that support it. +- **Build fails with missing headers**: Verify your deployment target is set to `13.0` or higher in both your Xcode project and `Podfile`/`Package.swift`. diff --git a/example/ios/Runner/AppDelegate.m b/example/ios/Runner/AppDelegate.m index d76db9f9..f9b28f8a 100644 --- a/example/ios/Runner/AppDelegate.m +++ b/example/ios/Runner/AppDelegate.m @@ -2,9 +2,18 @@ #import "GeneratedPluginRegistrant.h" #import +#if __has_include() +#import +#else #import "CleverTap.h" +#endif +#if __has_include() +#import +#import +#else #import "CleverTapPlugin.h" #import "CleverTapPluginCustomTemplates.h" +#endif @implementation AppDelegate diff --git a/ios/.gitignore b/ios/.gitignore index aa479fd3..fe343d53 100644 --- a/ios/.gitignore +++ b/ios/.gitignore @@ -34,4 +34,6 @@ Icon? .tags* /Flutter/Generated.xcconfig -/Flutter/flutter_export_environment.sh \ No newline at end of file +/Flutter/flutter_export_environment.sh + +.swiftpm/ \ No newline at end of file diff --git a/ios/clevertap_plugin.podspec b/ios/clevertap_plugin.podspec index 7777a58b..63368ab1 100644 --- a/ios/clevertap_plugin.podspec +++ b/ios/clevertap_plugin.podspec @@ -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' end diff --git a/ios/clevertap_plugin/Package.swift b/ios/clevertap_plugin/Package.swift new file mode 100644 index 00000000..46a36e2a --- /dev/null +++ b/ios/clevertap_plugin/Package.swift @@ -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" + ) + ], + targets: [ + .target( + name: "clevertap_plugin", + dependencies: [ + .product(name: "CleverTapSDK", package: "clevertap-ios-sdk") + ], + publicHeadersPath: "include/clevertap_plugin", + cSettings: [ + .headerSearchPath("include/clevertap_plugin") + ] + ) + ] +) diff --git a/ios/Classes/CleverTapPlugin.m b/ios/clevertap_plugin/Sources/clevertap_plugin/CleverTapPlugin.m similarity index 97% rename from ios/Classes/CleverTapPlugin.m rename to ios/clevertap_plugin/Sources/clevertap_plugin/CleverTapPlugin.m index 5daa8513..0d988e98 100644 --- a/ios/Classes/CleverTapPlugin.m +++ b/ios/clevertap_plugin/Sources/clevertap_plugin/CleverTapPlugin.m @@ -1,21 +1,101 @@ +#if __has_include() +#import +#else #import "CleverTap.h" +#endif + #import "CleverTapPlugin.h" + +#if __has_include() +#import +#else #import "CleverTap+Inbox.h" +#endif + +#if __has_include() +#import +#else #import "CleverTapUTMDetail.h" +#endif + +#if __has_include() +#import +#else #import "CleverTapEventDetail.h" +#endif + +#if __has_include() +#import +#else #import "CleverTapSyncDelegate.h" +#endif + +#if __has_include() +#import +#else #import "CleverTap+DisplayUnit.h" +#endif + +#if __has_include() +#import +#else #import "CleverTap+FeatureFlags.h" +#endif + +#if __has_include() +#import +#else #import "CleverTap+ProductConfig.h" +#endif + +#if __has_include() +#import +#else #import "CleverTapPushNotificationDelegate.h" +#endif + +#if __has_include() +#import +#else #import "CleverTapInAppNotificationDelegate.h" +#endif + +#if __has_include() +#import +#else #import "CleverTap+InAppNotifications.h" +#endif + +#if __has_include() +#import +#else #import "CleverTap+PushPermission.h" +#endif + +#if __has_include() +#import +#else #import "CTLocalInApp.h" +#endif + +#if __has_include() +#import +#else #import "CleverTap+CTVar.h" +#endif + +#if __has_include() +#import +#else #import "CTVar.h" +#endif + +#if __has_include() +#import +#else #import "CTTemplateContext.h" +#endif @interface CleverTapPlugin () diff --git a/ios/Classes/CleverTapPluginAppFunctionPresenter.m b/ios/clevertap_plugin/Sources/clevertap_plugin/CleverTapPluginAppFunctionPresenter.m similarity index 100% rename from ios/Classes/CleverTapPluginAppFunctionPresenter.m rename to ios/clevertap_plugin/Sources/clevertap_plugin/CleverTapPluginAppFunctionPresenter.m diff --git a/ios/Classes/CleverTapPluginCustomTemplates.m b/ios/clevertap_plugin/Sources/clevertap_plugin/CleverTapPluginCustomTemplates.m similarity index 89% rename from ios/Classes/CleverTapPluginCustomTemplates.m rename to ios/clevertap_plugin/Sources/clevertap_plugin/CleverTapPluginCustomTemplates.m index d5eaae46..da35cdde 100644 --- a/ios/Classes/CleverTapPluginCustomTemplates.m +++ b/ios/clevertap_plugin/Sources/clevertap_plugin/CleverTapPluginCustomTemplates.m @@ -9,8 +9,18 @@ #import "CleverTapPluginCustomTemplates.h" #import "CleverTapPluginTemplatePresenter.h" #import "CleverTapPluginAppFunctionPresenter.h" + +#if __has_include() +#import +#else #import "CTJsonTemplateProducer.h" +#endif + +#if __has_include() +#import +#else #import "CTCustomTemplatesManager.h" +#endif @implementation CleverTapPluginCustomTemplates diff --git a/ios/Classes/CleverTapPluginTemplatePresenter.m b/ios/clevertap_plugin/Sources/clevertap_plugin/CleverTapPluginTemplatePresenter.m similarity index 100% rename from ios/Classes/CleverTapPluginTemplatePresenter.m rename to ios/clevertap_plugin/Sources/clevertap_plugin/CleverTapPluginTemplatePresenter.m diff --git a/ios/Classes/CleverTapPlugin.h b/ios/clevertap_plugin/Sources/clevertap_plugin/include/clevertap_plugin/CleverTapPlugin.h similarity index 100% rename from ios/Classes/CleverTapPlugin.h rename to ios/clevertap_plugin/Sources/clevertap_plugin/include/clevertap_plugin/CleverTapPlugin.h diff --git a/ios/Classes/CleverTapPluginAppFunctionPresenter.h b/ios/clevertap_plugin/Sources/clevertap_plugin/include/clevertap_plugin/CleverTapPluginAppFunctionPresenter.h similarity index 100% rename from ios/Classes/CleverTapPluginAppFunctionPresenter.h rename to ios/clevertap_plugin/Sources/clevertap_plugin/include/clevertap_plugin/CleverTapPluginAppFunctionPresenter.h diff --git a/ios/Classes/CleverTapPluginCustomTemplates.h b/ios/clevertap_plugin/Sources/clevertap_plugin/include/clevertap_plugin/CleverTapPluginCustomTemplates.h similarity index 100% rename from ios/Classes/CleverTapPluginCustomTemplates.h rename to ios/clevertap_plugin/Sources/clevertap_plugin/include/clevertap_plugin/CleverTapPluginCustomTemplates.h diff --git a/ios/Classes/CleverTapPluginTemplatePresenter.h b/ios/clevertap_plugin/Sources/clevertap_plugin/include/clevertap_plugin/CleverTapPluginTemplatePresenter.h similarity index 100% rename from ios/Classes/CleverTapPluginTemplatePresenter.h rename to ios/clevertap_plugin/Sources/clevertap_plugin/include/clevertap_plugin/CleverTapPluginTemplatePresenter.h diff --git a/pubspec.yaml b/pubspec.yaml index 448f14b9..f5c4a582 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ homepage: https://github.com/CleverTap/clevertap-flutter environment: sdk: '>=2.12.0 <4.0.0' - flutter: ">=1.17.0" + flutter: ">=3.41.0" dependencies: flutter: @@ -28,6 +28,7 @@ flutter: pluginClass: CleverTapPlugin ios: pluginClass: CleverTapPlugin + swiftPackageName: clevertap_plugin web: pluginClass: CleverTapPluginWeb fileName: clevertap_plugin_web.dart