From 9e47b14700c4ff67dada742a8c9cf6af5379de64 Mon Sep 17 00:00:00 2001
From: Abhishek Pandey <64667840+1abhishekpandey@users.noreply.github.com>
Date: Thu, 7 Mar 2024 19:14:48 +0530
Subject: [PATCH 1/3] chore: remove lingering reference to deleted RudderConfig
 file

---
 .../RudderSampleAppObjC.xcodeproj/project.pbxproj             | 4 ----
 1 file changed, 4 deletions(-)

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 = "<group>"; };
 		ED8738CA2AB363A80076D24A /* EncryptedDatabaseProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EncryptedDatabaseProvider.h; sourceTree = "<group>"; };
 		ED8738CC2AB363A80076D24A /* EncryptedDatabaseProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EncryptedDatabaseProvider.m; sourceTree = "<group>"; };
-		F6149CC42B32FBC2006995B7 /* RudderConfig.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = RudderConfig.plist; sourceTree = "<group>"; };
 		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 = "<group>"; };
 /* 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 */,

From c56b825baa1fccf39e4b145c3f8d8e1d2c318d04 Mon Sep 17 00:00:00 2001
From: Abhishek Pandey <64667840+1abhishekpandey@users.noreply.github.com>
Date: Mon, 11 Mar 2024 16:19:21 +0530
Subject: [PATCH 2/3] fix: create mutable copy of JSON seiralisation object

---
 Sources/Classes/RSUtils.m | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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;

From 3fc3574c8179685eaf363fb88613fcae54984797 Mon Sep 17 00:00:00 2001
From: Abhishek Pandey <64667840+1abhishekpandey@users.noreply.github.com>
Date: Mon, 11 Mar 2024 17:05:19 +0530
Subject: [PATCH 3/3] test: add case for merging externalId simulating app
 relaunch

---
 Tests/ContextTests.swift | 13 +++++++++++++
 1 file changed, 13 insertions(+)

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()