Skip to content

feat(ios): migrate to MotionTag iOS SDK 7.0.0#9

Merged
jaymaycry merged 3 commits into
mainfrom
feat/ios-motiontag-sdk-7
Jul 10, 2026
Merged

feat(ios): migrate to MotionTag iOS SDK 7.0.0#9
jaymaycry merged 3 commits into
mainfrom
feat/ios-motiontag-sdk-7

Conversation

@jaymaycry

Copy link
Copy Markdown
Contributor

Lands the MotionTag iOS SDK 7.0.0 migration on the canonical repo. The same three commits were already reviewed and merged on the jaymaycry fork (jaymaycry/react-native-motiontag#1) — this PR brings them here so release-please picks them up.

What's in it

  • feat(ios): migrate to MotionTag iOS SDK 7.0.0 — podspec ~> 6.5.0~> 7.0.0; the SDK adopted Swift 6 and its concurrency model, so MotionTagDelegateImpl is now @MainActor-isolated and all five delegate methods use their renamed signatures (trackingDidChange, locationAuthorizationDidChange, motionActivityAuthorizationDidChange, didUpdateLocation, dataUploadDidComplete). MotionTagBootstrap gains an async processBackgroundSessionEvents(identifier:) alongside the completion-handler form.
  • fix(plugin): chain super in the background URL session override — since SDK v7 the SDK no longer decides which background sessions are its own, so the generated AppDelegate override forwards every identifier and chains the completion handler through super, keeping ExpoAppDelegate subscribers running and the handler firing exactly once.
  • feat(ios): implement getUserToken, wifiOnlyDataTransfer and clearData — brings iOS to parity with the JS spec (previously Android-only).

No new Info.plist keys or background task identifiers; host apps need no changes.

Verification

Example app built, installed and rendered on the iOS 26 simulator with the SDK-7 delegate feeding permission state to JS (Expo 55 baseline this morning, re-verified today on the stacked Expo 57 branch). Physical-device golden path (JWT → start → events → stop) still worth a run before release.

Merging

Please merge with a merge commit (like #2), not squash — the three conventional-commit subjects need to reach release-please individually (2× feat, 1× fix).

🤖 Generated with Claude Code

https://claude.ai/code/session_012rn1KYa8uH8ikwK3AaHaLP

jaymaycry and others added 3 commits July 10, 2026 09:47
7.0.0 is a pure-Swift, fully @MainActor-isolated module with no Objective-C
surface. It ships no MotionTag.h / MotionTagSDK.h, so MotionTagModule.mm's
`#import <MotionTagSDK/MotionTagSDK.h>` no longer resolves; the SDK is reached
only through the Swift shim, whose generated header omits the now non-@objc
MotionTagDelegate conformance.

Because the delegate protocol is @mainactor and refines Sendable,
MotionTagDelegateImpl must be main-actor isolated, so every @objc entry point
is now called from the main queue. isTrackingActive stops resolving
synchronously on the JS thread; JS already awaited a Promise, so the observable
contract is unchanged.

`MotionTag` is not class-constrained, so the cached `motionTag` existential has
to be a `var` for property writes to type-check. The conformer is a reference
type, so writes still reach the shared instance.

processBackgroundSessionEvents(with:) lost its completion-handler overload. The
async form is exposed as the primary shim; the completion-handler shim is kept
because ExpoAppDelegate declares only that spelling, in Swift, and Swift
synthesises the async spelling only for Objective-C declarations. Both public
signatures are unchanged, so host apps need no source change.

Note the vendor's prose guide is stale on two points the compiled interface
settles: the label is `launchOptions:`, not `launchOption:`, and its
`let motionTag: MotionTag` snippet does not compile.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0124GwP2xm3zYhoUiiSKWbeA
The injected override never called super, so ExpoAppDelegate's subscriber
fan-out was skipped entirely. That was masked under SDK v6, where the SDK
received the completion handler and invoked it only for its own sessions.

Since v7 the SDK no longer takes the handler, so our shim invokes it for every
identifier. Combined with a restored super call that would fire a background
completion handler twice, so the handler is now passed to super instead:
MotionTag drains its session first, then Expo's subscribers run and invoke the
handler exactly once.

Also switch the bare-RN README snippet to the async override, which lets a host
that owns other background URL sessions await each in turn and leaves UIKit to
invoke the handler once.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0124GwP2xm3zYhoUiiSKWbeA
These were stubbed out as "not supported on iOS (MotionTag SDK v6)", but v6.5.0
already exposed userToken, wifiOnlyDataTransfer and clearData on its MotionTag
protocol. The comments were wrong, not the SDK; the 7.0.0 migration only made
that visible.

getUserToken now resolves the stored JWT instead of null, getWifiOnlyDataTransfer
reports the real flag instead of false, and setWifiOnlyDataTransfer / clearData
resolve instead of rejecting UNSUPPORTED. clearData's record count is discarded:
the TS spec declares Promise<void> and Android resolves null.

isPowerSaveModeEnabled and isBatteryOptimizationsEnabled stay Android-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0124GwP2xm3zYhoUiiSKWbeA
@jaymaycry jaymaycry merged commit 93791c6 into main Jul 10, 2026
2 checks passed
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.

1 participant