Skip to content

Commit a9cf615

Browse files
authored
Merge pull request #894 from OneSignal/fix/iam-userdefaults-crashes
Fix IAM redisplay cache userdefaults crashes
2 parents 037fc8c + a51401d commit a9cf615

15 files changed

+110
-195
lines changed

iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@
6262
3E66F5821D90A2C600E45A01 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E08E2701D49A5C8002176DE /* SystemConfiguration.framework */; };
6363
4529DED21FA81EA800CEAB1D /* NSObjectOverrider.m in Sources */ = {isa = PBXBuildFile; fileRef = 4529DED11FA81EA800CEAB1D /* NSObjectOverrider.m */; };
6464
4529DED51FA823B900CEAB1D /* TestHelperFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = 4529DED41FA823B900CEAB1D /* TestHelperFunctions.m */; };
65-
4529DED81FA8253D00CEAB1D /* NSUserDefaultsOverrider.m in Sources */ = {isa = PBXBuildFile; fileRef = 4529DED71FA8253D00CEAB1D /* NSUserDefaultsOverrider.m */; };
6665
4529DEDB1FA8284E00CEAB1D /* NSDataOverrider.m in Sources */ = {isa = PBXBuildFile; fileRef = 4529DEDA1FA8284E00CEAB1D /* NSDataOverrider.m */; };
6766
4529DEDE1FA828E500CEAB1D /* NSDateOverrider.m in Sources */ = {isa = PBXBuildFile; fileRef = 4529DEDD1FA828E500CEAB1D /* NSDateOverrider.m */; };
6867
4529DEE11FA82AB300CEAB1D /* NSBundleOverrider.m in Sources */ = {isa = PBXBuildFile; fileRef = 4529DEE01FA82AB300CEAB1D /* NSBundleOverrider.m */; };
@@ -524,8 +523,6 @@
524523
4529DED11FA81EA800CEAB1D /* NSObjectOverrider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NSObjectOverrider.m; sourceTree = "<group>"; };
525524
4529DED31FA823B900CEAB1D /* TestHelperFunctions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestHelperFunctions.h; sourceTree = "<group>"; };
526525
4529DED41FA823B900CEAB1D /* TestHelperFunctions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestHelperFunctions.m; sourceTree = "<group>"; };
527-
4529DED61FA8253D00CEAB1D /* NSUserDefaultsOverrider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSUserDefaultsOverrider.h; sourceTree = "<group>"; };
528-
4529DED71FA8253D00CEAB1D /* NSUserDefaultsOverrider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NSUserDefaultsOverrider.m; sourceTree = "<group>"; };
529526
4529DED91FA8284E00CEAB1D /* NSDataOverrider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSDataOverrider.h; sourceTree = "<group>"; };
530527
4529DEDA1FA8284E00CEAB1D /* NSDataOverrider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NSDataOverrider.m; sourceTree = "<group>"; };
531528
4529DEDC1FA828E500CEAB1D /* NSDateOverrider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSDateOverrider.h; sourceTree = "<group>"; };
@@ -926,8 +923,6 @@
926923
4529DED11FA81EA800CEAB1D /* NSObjectOverrider.m */,
927924
4529DEE21FA82C6200CEAB1D /* NSURLSessionOverrider.h */,
928925
4529DEE31FA82C6200CEAB1D /* NSURLSessionOverrider.m */,
929-
4529DED61FA8253D00CEAB1D /* NSUserDefaultsOverrider.h */,
930-
4529DED71FA8253D00CEAB1D /* NSUserDefaultsOverrider.m */,
931926
4529DEEB1FA83C5D00CEAB1D /* OneSignalHelperOverrider.h */,
932927
4529DEEC1FA83C5D00CEAB1D /* OneSignalHelperOverrider.m */,
933928
CA08FC821FE99BB4004C445F /* OneSignalClientOverrider.h */,
@@ -1953,7 +1948,6 @@
19531948
CA63AF8720211FF800E340FB /* UnitTestCommonMethods.m in Sources */,
19541949
CA70E3372023D51300019273 /* OneSignalSetEmailParameters.m in Sources */,
19551950
7A5A8185248990CD002E07C8 /* OSIndirectNotification.m in Sources */,
1956-
4529DED81FA8253D00CEAB1D /* NSUserDefaultsOverrider.m in Sources */,
19571951
4529DEED1FA83C5D00CEAB1D /* OneSignalHelperOverrider.m in Sources */,
19581952
7AF98666244975AD00C36EAE /* OSOutcomeSourceBody.m in Sources */,
19591953
CA1A6E6C20DC2E31001C41B9 /* OneSignalDialogController.m in Sources */,

iOS_SDK/OneSignalSDK/Source/OSMessagingController.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ - (void)deleteOldRedisplayedInAppMessages {
204204
[newRedisplayDictionary removeObjectForKey:messageId];
205205
}
206206

207-
[OneSignalUserDefaults.initStandard saveDictionaryForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:newRedisplayDictionary];
207+
[OneSignalUserDefaults.initStandard saveCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:newRedisplayDictionary];
208208
}
209209
}
210210

iOS_SDK/OneSignalSDK/Source/OSMigrationController.m

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ of this software and associated documentation files (the "Software"), to deal
3434
#import "OneSignal.h"
3535
#import "OneSignalUserDefaults.h"
3636
#import "OneSignalCommonDefines.h"
37+
#import "OSInAppMessagingDefines.h"
3738
#import "OneSignalHelper.h"
3839

3940
@interface OneSignal ()
@@ -45,6 +46,7 @@ @implementation OSMigrationController
4546

4647
- (void)migrate {
4748
[self migrateToVersion_02_14_00_AndGreater];
49+
[self migrateIAMRedisplayCache];
4850
[self saveCurrentSDKVersion];
4951
}
5052

@@ -78,6 +80,36 @@ - (void)migrateToVersion_02_14_00_AndGreater {
7880
}
7981
}
8082

83+
// Devices could potentially have bad data in the OS_IAM_REDISPLAY_DICTIONARY
84+
// that was saved as a dictionary and not CodeableData. Try to detect if that is the case
85+
// and save it is as CodeableData instead.
86+
- (void)migrateIAMRedisplayCache {
87+
let iamRedisplayCacheFixVersion = 30203;
88+
long sdkVersion = [OneSignalUserDefaults.initShared getSavedIntegerForKey:OSUD_CACHED_SDK_VERSION defaultValue:0];
89+
if (sdkVersion >= iamRedisplayCacheFixVersion)
90+
return;
91+
92+
@try {
93+
__unused NSMutableDictionary *redisplayDict =[[NSMutableDictionary alloc] initWithDictionary:[OneSignalUserDefaults.initStandard
94+
getSavedCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY
95+
defaultValue:[NSMutableDictionary new]]];
96+
} @catch (NSException *exception) {
97+
@try {
98+
// The redisplay IAMs might have been saved as a dictionary.
99+
// Try to read them as a dictionary and then save them as a codeable.
100+
NSMutableDictionary *redisplayDict = [[NSMutableDictionary alloc] initWithDictionary:[OneSignalUserDefaults.initStandard
101+
getSavedDictionaryForKey:OS_IAM_REDISPLAY_DICTIONARY
102+
defaultValue:[NSMutableDictionary new]]];
103+
[OneSignalUserDefaults.initStandard saveCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY
104+
withValue:redisplayDict];
105+
} @catch (NSException *exception) {
106+
//Clear the cached redisplay dictionary of bad data
107+
[OneSignalUserDefaults.initStandard saveCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY
108+
withValue:nil];
109+
}
110+
}
111+
}
112+
81113
- (void)saveCurrentSDKVersion {
82114
let currentVersion = [[OneSignal sdkVersionRaw] intValue];
83115
[OneSignalUserDefaults.initShared saveIntegerForKey:OSUD_CACHED_SDK_VERSION withValue:currentVersion];

iOS_SDK/OneSignalSDK/UnitTests/BadgeTests.m

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ of this software and associated documentation files (the "Software"), to deal
2828
#import <XCTest/XCTest.h>
2929
#import "UnitTestCommonMethods.h"
3030
#import "OneSignalExtensionBadgeHandler.h"
31-
#import "NSUserDefaultsOverrider.h"
3231
#import "UNUserNotificationCenterOverrider.h"
3332
#import "UNUserNotificationCenter+OneSignal.h"
3433
#import "OneSignalHelperOverrider.h"
@@ -52,7 +51,7 @@ - (void)setUp {
5251

5352
UNUserNotificationCenterOverrider.authorizationStatus = [NSNumber numberWithInteger:UNAuthorizationStatusAuthorized];
5453

55-
[NSUserDefaultsOverrider clearInternalDictionary];
54+
[UnitTestCommonMethods clearUserDefaults];
5655
}
5756

5857
/*

iOS_SDK/OneSignalSDK/UnitTests/EmailTests.m

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ of this software and associated documentation files (the "Software"), to deal
4141
#import "UNUserNotificationCenterOverrider.h"
4242
#import "UNUserNotificationCenter+OneSignal.h"
4343
#import "NSBundleOverrider.h"
44-
#import "NSUserDefaultsOverrider.h"
4544
#import "OneSignalCommonDefines.h"
4645
#import "OneSignalTracker.h"
4746
#import "OneSignalInternal.h"

iOS_SDK/OneSignalSDK/UnitTests/InAppMessagingIntegrationTests.m

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ of this software and associated documentation files (the "Software"), to deal
4444
#import "UIApplicationOverrider.h"
4545
#import "OneSignalHelperOverrider.h"
4646
#import "UNUserNotificationCenterOverrider.h"
47-
#import "NSUserDefaultsOverrider.h"
4847
#import "NSBundleOverrider.h"
4948
#import "UNUserNotificationCenter+OneSignal.h"
5049
#import "Requests.h"
@@ -544,7 +543,7 @@ - (void)testIAMWithNoTriggersDisplayOnePerSession_Redisplay {
544543

545544
message.displayStats.lastDisplayTime = firstInterval - delay;
546545
// Save IAM for redisplay
547-
[OneSignalUserDefaults.initStandard saveDictionaryForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:redisplayedInAppMessages];
546+
[OneSignalUserDefaults.initStandard saveCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:redisplayedInAppMessages];
548547
// Set data for redisplay
549548
[OSMessagingControllerOverrider setMessagesForRedisplay:redisplayedInAppMessages];
550549
// Save IAM for dismiss
@@ -680,11 +679,11 @@ - (void)testIAMRemoveFromCache_Redisplay {
680679
[redisplayedInAppMessages setObject:message2 forKey:message2.messageId];
681680

682681
[OSMessagingControllerOverrider setMessagesForRedisplay:redisplayedInAppMessages];
683-
[standardUserDefaults saveDictionaryForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:redisplayedInAppMessages];
682+
[standardUserDefaults saveCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:redisplayedInAppMessages];
684683

685684
[self initOneSignalWithInAppMessage:message];
686685

687-
let redisplayMessagesCache = [standardUserDefaults getSavedDictionaryForKey:OS_IAM_REDISPLAY_DICTIONARY defaultValue:nil];
686+
NSMutableDictionary *redisplayMessagesCache = [standardUserDefaults getSavedCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY defaultValue:nil];
688687
XCTAssertTrue([redisplayMessagesCache objectForKey:message1.messageId]);
689688
XCTAssertFalse([redisplayMessagesCache objectForKey:message2.messageId]);
690689
}

iOS_SDK/OneSignalSDK/UnitTests/MigrationTests.m

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
#import "UnitTestCommonMethods.h"
3838
#import "OneSignalUserDefaults.h"
3939
#import "OneSignalCommonDefines.h"
40+
#import "OSInAppMessagingDefines.h"
41+
#import "OneSignalUserDefaults.h"
42+
#import "OSInAppMessage.h"
43+
#import "OSInAppMessagingHelpers.h"
4044
#import "CommonAsserts.h"
4145

4246
@interface MigrationTests : XCTestCase
@@ -237,4 +241,55 @@ - (void)testCachedUniqueOutcomeToCachedUniqueOutcomeMigration {
237241
XCTAssertEqual([[OneSignal sdkVersionRaw] intValue], sdkVersionAfterMigration);
238242
}
239243

244+
- (void)testIAMCachedEmptyDictionaryToCachedCodeableMigration {
245+
NSDictionary<NSString *, OSInAppMessage *>*emptyDict = [NSMutableDictionary new];
246+
[OneSignalUserDefaults.initStandard saveDictionaryForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:emptyDict];
247+
248+
[migrationController migrate];
249+
}
250+
251+
- (void)testIAMCachedDictionaryToCachedCodeableMigration {
252+
NSMutableDictionary <NSString *, OSInAppMessage *> *emptyDict = [NSMutableDictionary new];
253+
254+
[OneSignalUserDefaults.initStandard saveDictionaryForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:emptyDict];
255+
256+
[migrationController migrate];
257+
258+
NSDictionary<NSString *, OSInAppMessage *>*retrievedDict = [OneSignalUserDefaults.initStandard
259+
getSavedCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY defaultValue:nil];
260+
XCTAssertEqualObjects(emptyDict, retrievedDict);
261+
}
262+
263+
- (void)testIAMCachedCodeableMigration {
264+
let limit = 5;
265+
let delay = 60;
266+
let message = [OSInAppMessageTestHelper testMessageWithRedisplayLimit:limit delay:@(delay)];
267+
message.isDisplayedInSession = true;
268+
NSMutableDictionary <NSString *, OSInAppMessage *> *redisplayedInAppMessages = [NSMutableDictionary new];
269+
[redisplayedInAppMessages setObject:message forKey:message.messageId];
270+
271+
[OneSignalUserDefaults.initStandard saveCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:redisplayedInAppMessages];
272+
273+
[migrationController migrate];
274+
275+
NSDictionary<NSString *, OSInAppMessage *>*retrievedDict = [OneSignalUserDefaults.initStandard
276+
getSavedCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY defaultValue:nil];
277+
XCTAssertEqualObjects(redisplayedInAppMessages, retrievedDict);
278+
}
279+
280+
- (void)testIAMNilCacheToNilMigration {
281+
282+
[OneSignalUserDefaults.initStandard saveDictionaryForKey:OS_IAM_REDISPLAY_DICTIONARY withValue:nil];
283+
284+
[migrationController migrate];
285+
286+
NSDictionary<NSString *, OSInAppMessage *>*retrievedDict = [OneSignalUserDefaults.initStandard
287+
getSavedCodeableDataForKey:OS_IAM_REDISPLAY_DICTIONARY defaultValue:nil];
288+
XCTAssertNil(retrievedDict);
289+
}
290+
291+
292+
293+
294+
240295
@end

iOS_SDK/OneSignalSDK/UnitTests/OutcomeIntegrationTests.m

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ of this software and associated documentation files (the "Software"), to deal
4040
#import "UNUserNotificationCenterOverrider.h"
4141
#import "RestClientAsserts.h"
4242
#import "CommonAsserts.h"
43-
#import "NSUserDefaultsOverrider.h"
4443
#import "OneSignalClientOverrider.h"
4544
#import "UIApplicationOverrider.h"
4645
#import "OneSignalNotificationServiceExtensionHandler.h"

iOS_SDK/OneSignalSDK/UnitTests/OutcomeIntegrationV2Tests.m

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
#import "UNUserNotificationCenterOverrider.h"
4242
#import "RestClientAsserts.h"
4343
#import "CommonAsserts.h"
44-
#import "NSUserDefaultsOverrider.h"
4544
#import "OneSignalClientOverrider.h"
4645
#import "UIApplicationOverrider.h"
4746
#import "OneSignalNotificationServiceExtensionHandler.h"

iOS_SDK/OneSignalSDK/UnitTests/ProvisionalAuthorizationTests.m

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ of this software and associated documentation files (the "Software"), to deal
2828
#import <XCTest/XCTest.h>
2929
#import "UnitTestCommonMethods.h"
3030
#import "OneSignalExtensionBadgeHandler.h"
31-
#import "NSUserDefaultsOverrider.h"
3231
#import "UNUserNotificationCenterOverrider.h"
3332
#import "UNUserNotificationCenter+OneSignal.h"
3433
#import "OneSignalHelperOverrider.h"

0 commit comments

Comments
 (0)