Repository navigation
fix(iOS): build & test the example app via pure SwiftPM (d-date 9.0.2) + integration tests - #908
Merged
Merged
Conversation
The feature/spm branch depended on mdata-group/google-mlkit-swiftpm 9.0.0-simfix2, whose xcframeworks are arm64-only, are 33 KB stubs, and ship no models — so the example app could not build for the simulator. Switch to d-date/google-mlkit-swiftpm 9.0.2, which ships proper universal slices (arm64 + x86_64 simulator), real binaries, and bundled models: - Point all 11 plugin Package.swift manifests at d-date 9.0.2. - Wire the 19 ML Kit resource bundles into the example Xcode project and add -all_load. Bundles are gitignored and fetched via ios/download_mlkit_bundles.sh (documented in the README). - Fix entity_extraction, which was a silent no-op (it lacked the MLKitEntityExtraction product dependency, so canImport() was false). - Add an integration test suite (integration_test/) that exercises every plugin from bundled assets with no physical camera. MediaPipe-backed tests (pose, selfie segmentation) self-skip on the simulator; the iOS-unavailable APIs (face mesh, subject segmentation) assert their graceful "not implemented" stub. Result on the iOS simulator: 13 passed, 3 skipped, 0 failed.
pumano
force-pushed
the
feature/spm-fixes
branch
from
November 1, 2026 21:33
7d6aad4 to
3a09b7b
Compare
Collaborator
Author
|
@fbernaly Could you check it via real iphone? |
Collaborator
|
@pumano : I tested on a physical device and everything looks good! I just pushed a few dependency version updates. We're ready to merge this into |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Gets the
exampleapp building and its integration tests passing on the iOSsimulator using pure Swift Package Manager (no CocoaPods), and adds an
integration test suite that exercises every ML Kit plugin without a physical
camera.
On the iOS simulator the suite runs as
+13 ~3— 13 passed, 3 skipped,0 failed.
The problem
feature/spmdepended onmdata-group/google-mlkit-swiftpmat9.0.0-simfix2. That package is unusable for a simulator build:x86_64simulatorslice, so the universal build the Flutter tool forces
(
-destination "generic/platform=iOS Simulator") failed.Kit code.
mdata-group/google-mlkit-swiftpmis itself a fork ofd-date/google-mlkit-swiftpm. Switching to the upstreamd-datepackage at aproper release fixes all three at once.
The solution:
d-date/google-mlkit-swiftpm9.0.2d-daterepackages upstream ML Kit9.0.0as SPM binary-targetxcframeworks. Since
9.0.1it:ios-arm64(device) andios-arm64_x86_64-simulator. The arm64 simulator slice is synthesised from thedevice slice by rewriting the Mach-O platform, so no
EXCLUDED_ARCHSworkaround is needed and the Flutter universal build works;
detection and selfie segmentation;
Because SwiftPM cannot ship resource bundles inside a binary target, the model
resource bundles must be added to the app manually (see below).
What changed
Package manifests (11
Package.swift) — switched frommdata-group … 9.0.0-simfix2tod-date/google-mlkit-swiftpmexact: 9.0.2:barcode_scanning, commons, digital_ink_recognition, entity_extraction,
face_detection, image_labeling, language_id, object_detection, pose_detection,
selfie_segmentation, smart_reply, text_recognition, translation.
Example app (
packages/example)ios/Runner.xcodeproj/project.pbxproj— adds the 19 ML Kit resource bundles(file refs + an "MLKit Bundles" group + Resources phase) and
-all_loadinthe linker flags.
ios/mlkit_bundles/— the 19 bundles, gitignored (≈50 MB of model filesare not committed).
ios/download_mlkit_bundles.sh— new; fetches the bundles from thed-daterelease.
ios/.gitignore— ignoresmlkit_bundles/.ios/…/swiftpm/Package.resolved(×2) — pind-date9.0.2.ios/Runner/AppDelegate.swift— registers a tinyexample/simulatormethodchannel so tests can detect the simulator.
pubspec.yaml/pubspec.lock—integration_testdev-dependency.README.md— documents the one-time bundle download step.integration_test/ml_kit_integration_test.dart— new; the test suite.Plugin fix
google_mlkit_entity_extractionwas a silent no-op: it only depended oncommons, so#if canImport(MLKitEntityExtraction)was false and it returnedUNIMPLEMENTED. Added theMLKitEntityExtractionproduct so it genuinelyworks.
How it works (technical notes)
-ObjC+-all_load, every object file in the ML Kit static archives ispulled into
Runner.debug.dylib(≈530 MB in debug). The per-frameworkbinaries copied into
Runner.app/Frameworks/are small stubs; the symbols(
MLKTextRecognizer,MLKBarcodeScanner,MLKFaceDetector, …) live in theapp dylib. This is expected for statically-linked ML Kit.
-all_loadis required. Without it the ML Kit initializers (whichregister models/resources via
+load) are dead-stripped and recognizers failat runtime.
d-dateproduct iswired to it. The remaining stubs are correct because
d-date 9.0.2ships nosuch product:
document_scanner,face_mesh_detection,subject_segmentation, and the sixgenai_*plugins.Integration tests
integration_test/ml_kit_integration_test.dartcovers every plugin. Two inputhelpers avoid needing a real camera:
inputImageFromAsset(path)— copies a bundled asset to a temp file and buildsInputImage.fromFilePath(the file-path native path).bitmapFromAsset(path)— decodes an asset to raw RGBA and buildsInputImage.fromBitmap(the same shape a camera frame produces).MissingPluginException(no iOS API)MissingPluginException(no iOS API)All async ML Kit calls run inside
tester.runAsync(...).Why 3 tests are skipped
The 3 skips are all simulator limitations, not code problems:
pose detectionLOG(FATAL)inmediapipe::GpuBufferStorageCvPixelBuffer::GetTexture→abort(). That is a hard crash of the whole app that cannot be caught from Dart, so the test detects the simulator (via theexample/simulatorchannel) and skips. Runs on a real device.selfie segmentationcamera(smoke)availableCameras()is empty /initialize()throws (no permission granted). The test skips.Note that
face meshandsubject segmentationare not skipped: ML Kit hasno iOS API for them, so the plugins are graceful stubs returning
FlutterMethodNotImplemented. Those two tests pass on iOS by asserting theMissingPluginException(and run the real detection on Android).How to test
flutter analyzeon the example app: No issues found.Caveats
Runner.debug.dylib) because-all_loadpulls in all of ML Kit. Fine for tests; a release build is smaller.
download their models on first use, so those tests need network access.
simulator and must be verified on a real device.