diff --git a/Examples/RudderSampleAppObjC/RudderSampleAppObjC.xcodeproj/project.pbxproj b/Examples/RudderSampleAppObjC/RudderSampleAppObjC.xcodeproj/project.pbxproj index 320e321b..2d3d6a0d 100644 --- a/Examples/RudderSampleAppObjC/RudderSampleAppObjC.xcodeproj/project.pbxproj +++ b/Examples/RudderSampleAppObjC/RudderSampleAppObjC.xcodeproj/project.pbxproj @@ -24,7 +24,6 @@ ED761A062727E28800B086F4 /* CustomFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = ED7619FC2727E28800B086F4 /* CustomFactory.m */; }; ED761A072727E28800B086F4 /* _AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = ED7619FD2727E28800B086F4 /* _AppDelegate.m */; }; ED8738CE2AB363A80076D24A /* EncryptedDatabaseProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = ED8738CC2AB363A80076D24A /* EncryptedDatabaseProvider.m */; }; - F6149CC52B32FBC2006995B7 /* RudderConfig.plist in Resources */ = {isa = PBXBuildFile; fileRef = F6149CC42B32FBC2006995B7 /* RudderConfig.plist */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -57,7 +56,6 @@ ED7619FD2727E28800B086F4 /* _AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _AppDelegate.m; sourceTree = ""; }; ED8738CA2AB363A80076D24A /* EncryptedDatabaseProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EncryptedDatabaseProvider.h; sourceTree = ""; }; ED8738CC2AB363A80076D24A /* EncryptedDatabaseProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EncryptedDatabaseProvider.m; sourceTree = ""; }; - F6149CC42B32FBC2006995B7 /* RudderConfig.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = RudderConfig.plist; sourceTree = ""; }; F928F8A942558010CC7088BF /* Pods-RudderSampleAppObjC.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RudderSampleAppObjC.debug.xcconfig"; path = "Target Support Files/Pods-RudderSampleAppObjC/Pods-RudderSampleAppObjC.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -137,7 +135,6 @@ ED7619FD2727E28800B086F4 /* _AppDelegate.m */, ED7619F02727E28700B086F4 /* _ViewController.h */, ED7619F92727E28800B086F4 /* _ViewController.m */, - F6149CC42B32FBC2006995B7 /* RudderConfig.plist */, ED7619F22727E28700B086F4 /* CustomFactory.h */, ED7619FC2727E28800B086F4 /* CustomFactory.m */, ED7619FB2727E28800B086F4 /* CustomIntegration.h */, @@ -219,7 +216,6 @@ files = ( ED761A012727E28800B086F4 /* LaunchScreen.storyboard in Resources */, ED0CA6DE2A7D049E00899C1C /* SampleRudderConfig.plist in Resources */, - F6149CC52B32FBC2006995B7 /* RudderConfig.plist in Resources */, ED761A052727E28800B086F4 /* Images.xcassets in Resources */, ED7619FF2727E28800B086F4 /* InfoPlist.strings in Resources */, ED761A022727E28800B086F4 /* Main.storyboard in Resources */, diff --git a/Sources/Classes/RSUtils.m b/Sources/Classes/RSUtils.m index eb92e2d4..b4bc4d75 100644 --- a/Sources/Classes/RSUtils.m +++ b/Sources/Classes/RSUtils.m @@ -189,7 +189,7 @@ + (id _Nullable) deserialize:(NSString*) jsonString { @try { NSError *error = nil; NSData* data = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; - id object = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; + id object = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error]; if(error) { [RSLogger logError:[[NSString alloc] initWithFormat:@"RSUtils: deserialize: Failed to de-serialize the given string back to an object %@", jsonString]]; return nil; diff --git a/Tests/ContextTests.swift b/Tests/ContextTests.swift index 90f5b631..b2c4fbb0 100644 --- a/Tests/ContextTests.swift +++ b/Tests/ContextTests.swift @@ -169,6 +169,19 @@ class ContextTests: XCTestCase { XCTAssertEqual(context.externalIds, finalExternalIds) } + // This test case verifies the scenario when someone has made an identify call with some externalId and then app is stopped. + // At next app launch, externalId is read from the preferenceManager and then RSUtils.deserialize() returns the mutable externalId object. + // Now, if someone makes an indentify call with the same userId and externalId-type then externalId must be merged properly without any exception. + func test_updateExternalIds_simulatingAppRelaunche() { + guard let externalIdString = RSUtils.serialize(externalIds1) else { return XCTAssertThrowsError("externalIdString cannot be null") } + preferenceManager.saveExternalIds(externalIdString) + context = RSContext(config: RSConfig()) + + context.updateExternalIds(externalIds2) + + XCTAssertEqual(context.externalIds, finalExternalIds) + } + func test_persistExternalIds() { context.updateExternalIds(externalIds1) context.persistExternalIds()