-
Notifications
You must be signed in to change notification settings - Fork 264
fix: replace deprecated NSKeyedArchiver/NSKeyedUnarchiver APIs #1680
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
garvitkaushik-123
wants to merge
1
commit into
OneSignal:main
Choose a base branch
from
garvitkaushik-123:fix/replace-deprecated-NSKeyedUnarchiver-api
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 Minor behavior change to flag: the old
+[NSKeyedUnarchiver unarchiveObjectWithData:]threwNSExceptionon decode failures, whichmigrateIAMRedisplayCacheinOSInAppMessageMigrationController.m:50-68catches to trigger corrupt-cache recovery. The newinitForReadingFromData:error:+decodeTopLevelObjectAndReturnError:pair is documented to convert exceptions toNSErrorand return nil for some failure modes, so the recovery@catchmay no longer fire for genuinely-corrupt archive bytes. Impact is bounded (only devices upgrading from SDK < 3.2.03, no crash — corrupt entry just stays stale until the siblingmigrateToOSInAppMessageInternalclears it), but worth a defensiveif (!result && data) { @throw ... }if you want to preserve the original migration contract.Extended reasoning...
What changed
The PR replaces
+[NSKeyedUnarchiver unarchiveObjectWithData:]withinitForReadingFromData:error:+decodeTopLevelObjectAndReturnError:. Beyond the deprecation-warning fix, this changes the failure contract: the old API raisedNSExceptionon any decode failure (invalid archive bytes, missing class, wrong-type input), while the new API pair is explicitly designed to convert exceptions intoNSErrorreturn values.Where this matters
In
OSInAppMessageMigrationController.m:50-68,migrateIAMRedisplayCachewrapsgetSavedCodeableDataForKey:in@try/@catch (NSException *)specifically to detect legacy corrupt cache data. The comment on line 41-43 states the intent: "Devices could potentially have bad data in the OS_IAM_REDISPLAY_DICTIONARY that was saved as a dictionary and not CodeableData. Try to detect if that is the case…". When the@catchfires, the code re-reads the value as anNSDictionaryand re-saves it as archived data.Step-by-step trace (corrupt-NSData subcase)
NSUserDefaultsand a corruptNSDatablob stored underOS_IAM_REDISPLAY_DICTIONARY(e.g., partial write, unknown archive class).getSavedCodeableDataForKey:runs —[[NSKeyedUnarchiver alloc] initForReadingFromData:data error:nil]returns nil (per Apple docs for malformed archive headers).unarchiver.requiresSecureCoding = NOis a no-op (message to nil).[unarchiver decodeTopLevelObjectAndReturnError:nil]returns nil (message to nil).getSavedCodeableDataForKey:returnsnil— note it returnsresult(nil), notvalue(the default).migrateIAMRedisplayCache:[[NSMutableDictionary alloc] initWithDictionary:nil]on modern Foundation returns an empty mutable dict without throwing.@catchnever fires. Recovery path is skipped.Addressing the refutations
The strongest refutation argues (a)
decodingFailurePolicydefaults toRaiseExceptionand (b) wrong-type inputs (NSDictionarypassed whereNSDatais expected) still raiseNSInvalidArgumentExceptionvia unrecognized selector, so the@catchstill fires for the specific "saved-as-dictionary" case the migration was built for. These points have merit —decodeTopLevelObjectAndReturnError:is documented to catch internal exceptions and convert toNSError, and messaging-bytes/-lengthon anNSDictionaryreally would throw. So for the primary target case named in the migration comment (NSDictionary stored viasaveDictionaryForKey:earlier), the@catchlikely still triggers.However, the failure surface is narrower than before. Cases that previously all threw and now silently return nil include: (a)
NSDatawith corrupt archive bytes, (b) archive referencing an unmapped class (relevant becausemigrateIAMRedisplayCacheruns beforemigrateToOSInAppMessageInternalregisters theOSInAppMessage→OSInAppMessageInternalclass mapping on line 77), and (c) any decode failure that Apple has converted to error-return over the years. That is a real, documented API contract change on a code path whose whole reason for existing is to catch decode failures.Severity rationale
Marking this a nit rather than blocking. Reasons: the migration is version-gated to
sdkVersion < 30203(SDK 3.02.03, ~2019); the affected user population — devices upgrading from that old SDK with genuinely corrupt cache — is small; the failure mode is silent (no crash, callers see empty state); andmigrateToOSInAppMessageInternalruns immediately after and clears the key if the result is empty, so the stale data eventually gets wiped even if not migrated to the new format. The behavior change is worth flagging so the author can decide whether to preserve the original contract, but is not a merge blocker.Suggested fix
If preserving the original migration contract is desired, capture the error and rethrow, e.g.:
Alternatively, restructure
migrateIAMRedisplayCacheto trigger the recovery path whengetSavedCodeableDataForKey:returns nil while the rawNSUserDefaultsvalue is non-nil.