Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 13 additions & 1 deletion .github/workflows/manual-prepare_release_branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ jobs:
sed -i "s/cloud.mindbox:mobile-sdk:.*/cloud.mindbox:mobile-sdk:$AND_VER'/" mindbox_android/android/build.gradle
echo " After:" && grep "cloud.mindbox:mobile-sdk" mindbox_android/android/build.gradle || true

# Fail the release if a version substitution didn't land (stale pin).
assert_pin() { grep -qE "$2" "$1" || { echo "ERROR: pattern /$2/ not found in $1 — substitution failed"; exit 1; }; }

echo "→ Bumping iOS native SDK in podspec"
echo " Before s.version:" && grep -E "s\.version" mindbox_ios/ios/mindbox_ios.podspec || true
sed -i -E "s/(s\.version *= *')[^']+(')/\1$IO_VER\2/" mindbox_ios/ios/mindbox_ios.podspec
Expand All @@ -166,10 +169,18 @@ jobs:
echo " Before Mindbox dependency:" && grep "s.dependency 'Mindbox'," mindbox_ios/ios/mindbox_ios.podspec || true
sed -i -E "s/(s\.dependency 'Mindbox', *')[^']+(')/\1$IO_VER\2/" mindbox_ios/ios/mindbox_ios.podspec
echo " After Mindbox dependency:" && grep "s.dependency 'Mindbox'," mindbox_ios/ios/mindbox_ios.podspec || true
assert_pin mindbox_ios/ios/mindbox_ios.podspec "s\.dependency 'Mindbox', *'$IO_VER'"

echo " Before Notifications dep:" && grep "MindboxNotifications" mindbox_ios/ios/mindbox_ios.podspec || true
sed -i -E "s/(s\.dependency 'MindboxNotifications', *')[^']+(')/\1$IO_VER\2/" mindbox_ios/ios/mindbox_ios.podspec
echo " After Notifications dep:" && grep "MindboxNotifications" mindbox_ios/ios/mindbox_ios.podspec || true
assert_pin mindbox_ios/ios/mindbox_ios.podspec "s\.dependency 'MindboxNotifications', *'$IO_VER'"

echo "→ Bumping ios-sdk exact pin in SPM manifest"
echo " Before:" && grep "mindbox-cloud/ios-sdk" mindbox_ios/ios/mindbox_ios/Package.swift || true
sed -i "/mindbox-cloud\/ios-sdk/ s/exact: \"[^\"]*\"/exact: \"$IO_VER\"/" mindbox_ios/ios/mindbox_ios/Package.swift
echo " After:" && grep "mindbox-cloud/ios-sdk" mindbox_ios/ios/mindbox_ios/Package.swift || true
assert_pin mindbox_ios/ios/mindbox_ios/Package.swift "exact: *\"$IO_VER\""

echo "→ Now inspect pubspec.yaml versions:"
echo " mindbox/pubspec.yaml:" && grep "^version\|mindbox_" mindbox/pubspec.yaml || true
Expand Down Expand Up @@ -207,7 +218,8 @@ jobs:
mindbox_ios/pubspec.yaml \
mindbox_platform_interface/pubspec.yaml \
mindbox_android/android/build.gradle \
mindbox_ios/ios/mindbox_ios.podspec
mindbox_ios/ios/mindbox_ios.podspec \
mindbox_ios/ios/mindbox_ios/Package.swift

git commit -m "Bump SDK versions: Flutter=$VERSION, Android=$AND_VER, iOS=$IO_VER"
echo "release_branch=$REL" >> $GITHUB_OUTPUT
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ flow don't need any code changes.

[flutter-uiscene]: https://docs.flutter.dev/release/breaking-changes/uiscenedelegate

### iOS Swift Package Manager

The plugin supports Swift Package Manager alongside CocoaPods. In SPM mode the
main app gets Mindbox automatically; notification extensions need a one-time
Xcode wiring step. See [SPM_MIGRATION.md](SPM_MIGRATION.md). CocoaPods users
need no changes.

## Troubleshooting

Refer to the [Example of integration(IOS)](https://github.com/mindbox-cloud/flutter-sdk/tree/develop/mindbox_ios/example) or [Example of integration(Android)](https://github.com/mindbox-cloud/flutter-sdk/tree/develop/mindbox_android/example) in case of any issues.
Expand Down
114 changes: 114 additions & 0 deletions SPM_MIGRATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Using the Mindbox Flutter SDK with Swift Package Manager

The plugin supports SPM alongside CocoaPods. Flutter's SPM is opt-in (off by
default as of 3.44); the [official Flutter guide][flutter-spm-app] covers the
Flutter-side setup. This document covers only the Mindbox-specific glue.

On CocoaPods **nothing changes** — see [CocoaPods](#cocoapods) at the bottom.

## Prerequisites

- **Flutter ≥ 3.29.** Verified: on 3.29 the plugin resolves as an SPM product;
on 3.24 Flutter silently falls back to CocoaPods (SPM is not engaged, the SDK
comes in via the pod).
- Enable SPM:
- **Flutter ≥ 3.35** — globally with
`flutter config --enable-swift-package-manager`, or per project in
`pubspec.yaml`:
```yaml
flutter:
config:
enable-swift-package-manager: true
```
- **Flutter 3.29–3.34** — use the global flag only. The per-project `config:`
block is not recognized yet and makes `flutter pub get` fail with
`Unexpected child "config" found under "flutter"`.

## Main app — nothing to do

The `Runner` target gets `Mindbox` transitively through the plugin; `flutter
run` / `flutter build ios` resolve and link it for you.

If your `Podfile` declares `pod 'Mindbox'` on the `Runner` target, **remove it**
— Mindbox would then load via both CocoaPods and SPM. See
[Remove the Mindbox pods](#remove-the-mindbox-pods).

## Notification extensions — one manual step

An extension is a native target, so its dependencies come from your Xcode
project, not from Flutter. Wire them once in Xcode:

1. **Runner** project → **Package Dependencies** → **+**.
2. URL: `https://github.com/mindbox-cloud/ios-sdk`
3. **Dependency Rule → Up to Next Major Version**, starting at the SDK version
you use (e.g. `2.15.1`). Use a range, not "Exact" — see [Versions](#versions).
4. **Add Package**, then in **Choose Package Products**:

| Product | Add to target |
|---|---|
| `Mindbox` | **None** (Runner already gets it via the plugin) |
| `MindboxNotificationsService` | Notification **Service** Extension |
| `MindboxNotificationsContent` | Notification **Content** Extension |

Then remove the extensions' CocoaPods integration — see
[Remove the Mindbox pods](#remove-the-mindbox-pods) below.

## Remove the Mindbox pods

Once the main app gets `Mindbox` via the plugin and the extensions are wired to
the SPM products, remove **every** Mindbox-family pod from the `Podfile` — the
`Runner` target's `pod 'Mindbox'` and each extension's
`pod 'MindboxNotifications'`:

```ruby
# DELETE — these are provided by SPM now
pod 'Mindbox' # in the Runner target
pod 'MindboxNotifications' # in each notification-extension target
```

Loading the same native SDK through both CocoaPods and SPM links it twice; at
runtime you get duplicate Swift classes and a Core Data crash
(`Fatal error: ... Expected CDEvent but found CDEvent`). Keep every non-Mindbox
pod, then re-run `pod install` (or just `flutter run`).

No `flutter clean` or `pod deintegrate` is needed: Flutter re-adds the SPM
integration on the next build and `pod install` drops the now-unused pods.

If **all** your plugins support SPM (not just Mindbox), you can drop CocoaPods
entirely instead of keeping the hybrid setup — delete the `Podfile` and run
`pod deintegrate`. See the reference example below.

## Versions

SPM identifies a package by URL, so the project-level `ios-sdk` and the one the
plugin pulls in are the same package, resolved to a single version. The plugin
pins an exact version; your "Up to Next Major" range only has to include it.
Don't pin the project to a different "Exact" version — SPM fails the build with
a clear conflict error instead of shipping two versions.

## Unchanged

- Your `AppDelegate`, `Mindbox.shared.*` calls, push handling, in-app callbacks.
- `UISceneDelegate` migration ([UISCENE_MIGRATION.md](UISCENE_MIGRATION.md)) is
orthogonal to SPM.
- The Objective-C `MindboxFlutterAppDelegateObjc` base class is
**CocoaPods-only** and deprecated; SPM consumers use the Swift
`MindboxFlutterAppDelegate` or call `Mindbox.shared.*` from their own
AppDelegate.

## Reference

[`example/flutter_example`](https://github.com/mindbox-cloud/flutter-sdk/tree/develop/example/flutter_example)
is configured for **pure SPM**: both extensions wired as above and no CocoaPods
at all — every plugin it uses ships SPM, so the `Podfile` was removed
(`pod deintegrate`). A real app keeps CocoaPods only if it still depends on
plugins that don't support SPM yet.

## CocoaPods

If SPM is off (the default), nothing changes: the main app gets the pods via
the plugin's podspec, and your extension targets declare
`pod 'MindboxNotifications'` in the `Podfile` as before. No code or project
changes are needed to update the SDK.

[flutter-spm-app]: https://docs.flutter.dev/packages-and-plugins/swift-package-manager/for-app-developers
13 changes: 9 additions & 4 deletions example/flutter_example/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ migrate_working_dir/
.pub/
/build/

# Local pub overrides (dev-only, wires example to local packages)
pubspec_overrides.yaml

# Xcode/Flutter SwiftPM workspace dir. Ignore the per-machine scratch
# (configuration/) but COMMIT Package.resolved — this is an app, so its SPM
# lockfile is checked in for reproducible native-SDK resolution.
**/xcshareddata/swiftpm/*
!**/xcshareddata/swiftpm/Package.resolved

# Symbolication related
app.*.symbols

Expand All @@ -47,9 +56,5 @@ app.*.map.json
/android/app/google-services.json
/android/app/agconnect-services.json

# iOS
/ios/Pods/
/ios/Podfile.lock

# FVM Version Cache
.fvm/
1 change: 0 additions & 1 deletion example/flutter_example/ios/Flutter/Debug.xcconfig
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
1 change: 0 additions & 1 deletion example/flutter_example/ios/Flutter/Release.xcconfig
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
72 changes: 0 additions & 72 deletions example/flutter_example/ios/Podfile

This file was deleted.

Loading
Loading