Skip to content

fix: NSKeyedUnarchiver class mappings for MPUploadSettings backward compat#666

Open
nickolas-dimitrakas wants to merge 2 commits intoworkstation/9.0-Releasefrom
fix/upload-settings-unarchive-compat
Open

fix: NSKeyedUnarchiver class mappings for MPUploadSettings backward compat#666
nickolas-dimitrakas wants to merge 2 commits intoworkstation/9.0-Releasefrom
fix/upload-settings-unarchive-compat

Conversation

@nickolas-dimitrakas
Copy link
Contributor

@nickolas-dimitrakas nickolas-dimitrakas commented Mar 12, 2026

Background

PR #543 migrated MPUploadSettings from Swift to Obj-C, changing the module name from mParticle_Apple_SDK_NoLocation to mParticle_Apple_SDK. PR #469 attempted to fix backward compat for persisted data but used the wrong API (NSKeyedArchiver = encoding direction, no effect on decoding) and missed the SQLite decode path in MPPersistenceController.m.

What Has Changed

  • Added MPUploadSettings +initialize which registers legacy class name mappings on NSKeyedUnarchiver automatically — the Obj-C runtime fires this the first time [MPUploadSettings class] is evaluated, which happens in both decode paths as part of unarchivedObjectOfClass:[MPUploadSettings class]. No manual wiring needed anywhere.
  • Removed the incorrect NSKeyedArchiver calls from UploadSettingsUtils.m.

Tests Added

  • testFetchUploads_decodesLegacySwiftModuleClassName — saves an upload to SQLite with a settings blob encoded under the legacy Swift module class name, then verifies fetchUploads decodes and returns it correctly.
  • testRegisterUploadSettingsClassMappings_decodesAllModuleNames — verifies both legacy module names decode into MPUploadSettings successfully.

Impact Without This Fix

Users upgrading from a pre-migration SDK version lose queued upload data on first launch: fetchUploads silently drops rows it can't decode, and prepareBatchesForUpload:nil batches in-flight messages with no API credentials, causing server rejection.

Checklist

  • Self-review completed
  • Tests added or updated
  • Tested locally

…ckward compat

PR #469 used NSKeyedArchiver setClassName:forClass: (the encode direction) which
has no effect on decoding. This replaces it with NSKeyedUnarchiver setClass:forClassName:
(the decode direction) so persisted upload settings encoded under the old Swift module
name (mParticle_Apple_SDK_NoLocation.MPUploadSettings) can be decoded after upgrading
to the Obj-C module (mParticle_Apple_SDK.MPUploadSettings).

Also extends coverage to MPPersistenceController.m fetchUploads, which reads upload
settings blobs from the SQLite uploads table but was not covered by the original fix,
causing those rows to be silently skipped and never uploaded.

Without this fix, users upgrading from an SDK version where MPUploadSettings was a Swift
class will lose queued upload data on first launch post-upgrade.

Made-with: Cursor
@nickolas-dimitrakas nickolas-dimitrakas requested a review from a team as a code owner March 12, 2026 21:00
@github-actions
Copy link

github-actions bot commented Mar 12, 2026

📦 SDK Size Impact Report

Measures how much the SDK adds to an app's size (with-SDK minus without-SDK).

Metric Target Branch This PR Change
App Bundle Impact 1.65 MB 1.65 MB +N/A
Executable Impact 896 bytes 896 bytes +N/A
XCFramework Size 5.45 MB 5.45 MB +N/A

➡️ SDK size impact change is minimal.

Raw measurements

Target branch (workstation/9.0-Release):

{"baseline_app_size_kb":84,"baseline_executable_size_bytes":75464,"with_sdk_app_size_kb":1772,"with_sdk_executable_size_bytes":76360,"sdk_impact_kb":1688,"sdk_executable_impact_bytes":896,"xcframework_size_kb":5584}

This PR:

{"baseline_app_size_kb":84,"baseline_executable_size_bytes":75464,"with_sdk_app_size_kb":1772,"with_sdk_executable_size_bytes":76360,"sdk_impact_kb":1688,"sdk_executable_impact_bytes":896,"xcframework_size_kb":5584}

denischilik
denischilik previously approved these changes Mar 13, 2026
Copy link
Contributor

@denischilik denischilik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Collaborator

@jamesnrokt jamesnrokt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One comment but also are there any tests we could / should add?

@nickolas-dimitrakas
Copy link
Contributor Author

One comment but also are there any tests we could / should add?

Adding tests as you sent this

…+initialize

Move NSKeyedUnarchiver class name mappings from UploadSettingsUtils into
MPUploadSettings +initialize so they are registered automatically by the
Obj-C runtime the first time any decode path evaluates [MPUploadSettings class],
with no manual wiring required anywhere.

Also adds two unit tests:
- testFetchUploads_decodesLegacySwiftModuleClassName: verifies fetchUploads
  correctly decodes SQLite rows whose upload_settings blob was encoded under
  the legacy Swift module class name.
- testRegisterUploadSettingsClassMappings_decodesAllModuleNames: verifies both
  legacy module names (mParticle_Apple_SDK and mParticle_Apple_SDK_NoLocation)
  can be decoded into MPUploadSettings after the mapping is registered.

Made-with: Cursor
@nickolas-dimitrakas nickolas-dimitrakas changed the title fix: correct NSKeyedUnarchiver class mappings for MPUploadSettings backward compat fix: NSKeyedUnarchiver class mappings for MPUploadSettings backward compat Mar 13, 2026
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.

5 participants