From 99364bfbf62401c6d53b195b63a21576baaf354b Mon Sep 17 00:00:00 2001 From: Brandon Stalnaker <33703490+BrandonStalnaker@users.noreply.github.com> Date: Thu, 19 Feb 2026 11:16:08 -0500 Subject: [PATCH 1/7] fix: SceneDelegate Protocol Objc Selector Issue (#603) --- .../Mocks/MPAppNotificationHandlerMock.swift | 8 ++-- .../Mocks/SceneDelegateHandlerMock.swift | 12 +++-- .../MParticleSceneDelegateTests.swift | 47 +++++++++++++++---- .../SceneDelegateHandler.swift | 2 + 4 files changed, 52 insertions(+), 17 deletions(-) diff --git a/UnitTests/Mocks/MPAppNotificationHandlerMock.swift b/UnitTests/Mocks/MPAppNotificationHandlerMock.swift index 0ecb52687..d81c674ab 100644 --- a/UnitTests/Mocks/MPAppNotificationHandlerMock.swift +++ b/UnitTests/Mocks/MPAppNotificationHandlerMock.swift @@ -89,18 +89,20 @@ class MPAppNotificationHandlerMock: MPAppNotificationHandlerProtocol { var openURLWithOptionsCalled = false var openURLWithOptionsURLParam: URL? var openURLWithOptionsOptionsParam: [String: Any]? - + + @objc(openURL:options:) func open(_ url: URL, options: [String: Any]?) { openURLWithOptionsCalled = true openURLWithOptionsURLParam = url openURLWithOptionsOptionsParam = options } - + var continueUserActivityCalled = false var continueUserActivityUserActivityParam: NSUserActivity? var continueUserActivityRestorationHandlerParam: (([UIUserActivityRestoring]?) -> Void)? var continueUserActivityReturnValue: Bool = false - + + @objc(continueUserActivity:restorationHandler:) func `continue`(_ userActivity: NSUserActivity, restorationHandler: @escaping ([any UIUserActivityRestoring]?) -> Void) -> Bool { continueUserActivityCalled = true diff --git a/UnitTests/Mocks/SceneDelegateHandlerMock.swift b/UnitTests/Mocks/SceneDelegateHandlerMock.swift index 9a3b639db..018f50b57 100644 --- a/UnitTests/Mocks/SceneDelegateHandlerMock.swift +++ b/UnitTests/Mocks/SceneDelegateHandlerMock.swift @@ -5,23 +5,25 @@ import XCTest import mParticle_Apple_SDK #endif -class OpenURLHandlerProtocolMock: OpenURLHandlerProtocol { - +class OpenURLHandlerProtocolMock: NSObject, OpenURLHandlerProtocol { + var openURLWithOptionsCalled = false var openURLWithOptionsURLParam: URL? var openURLWithOptionsOptionsParam: [String: Any]? - + + @objc(openURL:options:) func open(_ url: URL, options: [String: Any]?) { openURLWithOptionsCalled = true openURLWithOptionsURLParam = url openURLWithOptionsOptionsParam = options } - + var continueUserActivityCalled = false var continueUserActivityUserActivityParam: NSUserActivity? var continueUserActivityRestorationHandlerParam: (([UIUserActivityRestoring]?) -> Void)? var continueUserActivityReturnValue: Bool = false - + + @objc(continueUserActivity:restorationHandler:) func continueUserActivity( _ userActivity: NSUserActivity, restorationHandler: @escaping ([any UIUserActivityRestoring]?) -> Void diff --git a/UnitTests/SwiftTests/MParticle/MParticleSceneDelegateTests.swift b/UnitTests/SwiftTests/MParticle/MParticleSceneDelegateTests.swift index 3eb372198..04304374d 100644 --- a/UnitTests/SwiftTests/MParticle/MParticleSceneDelegateTests.swift +++ b/UnitTests/SwiftTests/MParticle/MParticleSceneDelegateTests.swift @@ -7,27 +7,56 @@ import mParticle_Apple_SDK import XCTest final class MParticleSceneDelegateTests: XCTestCase { - + // MARK: - Properties var mparticle: MParticle! var sceneMock: OpenURLHandlerProtocolMock! - var testURL: URL! var testUserActivity: NSUserActivity! - + override func setUp() { super.setUp() mparticle = MParticle() - testURL = URL(string: "myapp://test/path?param=value")! testUserActivity = NSUserActivity(activityType: "com.test.activity") testUserActivity.title = "Test Activity" testUserActivity.userInfo = ["key": "value"] - - // The implementation calls [MParticle sharedInstance], so we need to set the mock on the shared instance + sceneMock = OpenURLHandlerProtocolMock() let sceneHandler = SceneDelegateHandler(logger: MPLog(logLevel: .verbose), appNotificationHandler: sceneMock) mparticle.sceneDelegateHandler = sceneHandler } + + // MARK: - Protocol Selector Tests + + func test_openURLHandlerProtocol_respondsToOpenURLSelector() { + // This test verifies that the protocol method maps to the correct ObjC selector + let handler: OpenURLHandlerProtocol = sceneMock + let selector = NSSelectorFromString("openURL:options:") + XCTAssertTrue((handler as AnyObject).responds(to: selector), + "OpenURLHandlerProtocol should respond to openURL:options: selector") + } + + func test_openURLHandlerProtocol_respondsToContiuneUserActivitySelector() { + // This test verifies that the protocol method maps to the correct ObjC selector + let handler: OpenURLHandlerProtocol = sceneMock + let selector = NSSelectorFromString("continueUserActivity:restorationHandler:") + XCTAssertTrue((handler as AnyObject).responds(to: selector), + "OpenURLHandlerProtocol should respond to continueUserActivity:restorationHandler: selector") + } + + func test_mpAppNotificationHandler_respondsToOpenURLHandlerProtocolSelectors() { + // This test verifies that MPAppNotificationHandler responds to the selectors + // expected by OpenURLHandlerProtocol + let handler = MPAppNotificationHandler() + + let openURLSelector = NSSelectorFromString("openURL:options:") + XCTAssertTrue(handler.responds(to: openURLSelector), + "MPAppNotificationHandler must respond to openURL:options: to conform to OpenURLHandlerProtocol") + + let continueActivitySelector = NSSelectorFromString("continueUserActivity:restorationHandler:") + XCTAssertTrue(handler.responds(to: continueActivitySelector), + "MPAppNotificationHandler must respond to continueUserActivity:restorationHandler: to conform to OpenURLHandlerProtocol") + } // MARK: - handleUserActivity Tests @@ -58,14 +87,14 @@ final class MParticleSceneDelegateTests: XCTestCase { func test_handleUserActivity_restorationHandlerIsEmpty() { // Act mparticle.handleUserActivity(testUserActivity) - + // Assert XCTAssertTrue(sceneMock.continueUserActivityCalled) - + // Verify the restoration handler is provided and safe to call let restorationHandler = sceneMock.continueUserActivityRestorationHandlerParam XCTAssertNotNil(restorationHandler) - + // Test that calling the restoration handler doesn't crash XCTAssertNoThrow(restorationHandler?(nil)) XCTAssertNoThrow(restorationHandler?([])) diff --git a/mParticle-Apple-SDK/SceneDelegateHandler.swift b/mParticle-Apple-SDK/SceneDelegateHandler.swift index ba9e9836d..4a9bace49 100644 --- a/mParticle-Apple-SDK/SceneDelegateHandler.swift +++ b/mParticle-Apple-SDK/SceneDelegateHandler.swift @@ -2,7 +2,9 @@ import Foundation @objc public protocol OpenURLHandlerProtocol { + @objc(openURL:options:) func open(_ url: URL, options: [String: Any]?) + @objc(continueUserActivity:restorationHandler:) func continueUserActivity( _ userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void From 37c277c3a9fd43ac8cc90e974f2db73d3b370ccd Mon Sep 17 00:00:00 2001 From: mParticle Bot User Date: Thu, 19 Feb 2026 11:52:27 -0500 Subject: [PATCH 2/7] chore: Release v8.44.0 (#605) chore: (release) 8.44.0 Updates version to 8.44.0 in: - CHANGELOG.md - Framework/Info.plist - Package.swift - mParticle-Apple-SDK.podspec - mParticle-Apple-SDK/MPConstants.swift - mParticle-Apple-SDK/MPIConstants.m - mParticle_Apple_SDK.json - IntegrationTests/wiremock-recordings/mappings/*.json --- CHANGELOG.md | 6 ++++++ Framework/Info.plist | 2 +- .../mappings/mapping-ccpa-consent.json | 2 +- .../mappings/mapping-commerce-event-purchase.json | 2 +- .../mappings/mapping-gdpr-consent.json | 2 +- .../mappings/mapping-increment-session-attribute-ss.json | 2 +- .../mappings/mapping-increment-session-attribute.json | 2 +- .../mappings/mapping-increment-user-attribute-set.json | 2 +- .../mappings/mapping-increment-user-attribute.json | 2 +- .../wiremock-recordings/mappings/mapping-log-error.json | 2 +- .../mappings/mapping-log-event-with-flags.json | 2 +- .../mappings/mapping-log-exception.json | 2 +- .../wiremock-recordings/mappings/mapping-log-idfa.json | 2 +- .../wiremock-recordings/mappings/mapping-log-screen.json | 2 +- .../mappings/mapping-rokt-identify.json | 2 +- .../mappings/mapping-rokt-select-placement.json | 2 +- .../mappings/mapping-set-att-status.json | 2 +- .../mappings/mapping-set-session-attribute.json | 2 +- .../mappings/mapping-set-user-attributes.json | 2 +- .../wiremock-recordings/mappings/mapping-timed-event.json | 2 +- .../wiremock-recordings/mappings/mapping-v1-identify.json | 2 +- .../mappings/mapping-v2-events-log-event.json | 2 +- Package.swift | 8 ++++---- mParticle-Apple-SDK.podspec | 2 +- mParticle-Apple-SDK/MPConstants.swift | 2 +- mParticle-Apple-SDK/MPIConstants.m | 2 +- mParticle_Apple_SDK.json | 3 ++- 27 files changed, 36 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df7521da1..81999adc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# [8.44.0](https://github.com/mParticle/mparticle-apple-sdk/compare/v8.43.1...v8.44.0) (2026-02-19) + +### Bug Fixes + +- fix: SceneDelegate Protocol Objc Selector Issue (#603) ([99364bfb](https://github.com/mParticle/mparticle-apple-sdk/commit/99364bfbf62401c6d53b195b63a21576baaf354b)) + # [8.43.1](https://github.com/mParticle/mparticle-apple-sdk/compare/v8.42.2...v8.43.1) (2026-02-16) ### Bug Fixes diff --git a/Framework/Info.plist b/Framework/Info.plist index c9656ac5d..3a210b676 100644 --- a/Framework/Info.plist +++ b/Framework/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 8.43.1 + 8.44.0 CFBundleSignature ???? CFBundleVersion diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-ccpa-consent.json b/IntegrationTests/wiremock-recordings/mappings/mapping-ccpa-consent.json index ff5cf1fe5..9dc356483 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-ccpa-consent.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-ccpa-consent.json @@ -69,7 +69,7 @@ ], "uitl": 60, "oo": false, - "sdk": "8.43.1", + "sdk": "8.44.0", "di": { "p": "arm64", "tz": "${json-unit.ignore}", diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-commerce-event-purchase.json b/IntegrationTests/wiremock-recordings/mappings/mapping-commerce-event-purchase.json index 5ab948633..ddafa0cd2 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-commerce-event-purchase.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-commerce-event-purchase.json @@ -81,7 +81,7 @@ ], "uitl": 60, "oo": false, - "sdk": "8.43.1", + "sdk": "8.44.0", "di": { "b": "arm64", "p": "arm64", diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-gdpr-consent.json b/IntegrationTests/wiremock-recordings/mappings/mapping-gdpr-consent.json index 066ab739a..0e717ccde 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-gdpr-consent.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-gdpr-consent.json @@ -59,7 +59,7 @@ ], "uitl": 60, "oo": false, - "sdk": "8.43.1", + "sdk": "8.44.0", "di": { "tz": "${json-unit.ignore}", "p": "arm64", diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-increment-session-attribute-ss.json b/IntegrationTests/wiremock-recordings/mappings/mapping-increment-session-attribute-ss.json index 1860ae1dd..0dd4f82df 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-increment-session-attribute-ss.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-increment-session-attribute-ss.json @@ -52,7 +52,7 @@ ], "uitl": 60, "oo": false, - "sdk": "8.43.1", + "sdk": "8.44.0", "di": { "b": "arm64", "tz": "${json-unit.ignore}", diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-increment-session-attribute.json b/IntegrationTests/wiremock-recordings/mappings/mapping-increment-session-attribute.json index b29751a69..0a43ec9ad 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-increment-session-attribute.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-increment-session-attribute.json @@ -58,7 +58,7 @@ ], "uitl": 60, "oo": false, - "sdk": "8.43.1", + "sdk": "8.44.0", "di": { "b": "arm64", "tz": "${json-unit.ignore}", diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-increment-user-attribute-set.json b/IntegrationTests/wiremock-recordings/mappings/mapping-increment-user-attribute-set.json index c23efc4ac..608efedb9 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-increment-user-attribute-set.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-increment-user-attribute-set.json @@ -56,7 +56,7 @@ ], "uitl": 60, "oo": false, - "sdk": "8.43.1", + "sdk": "8.44.0", "di": { "p": "arm64", "b": "arm64", diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-increment-user-attribute.json b/IntegrationTests/wiremock-recordings/mappings/mapping-increment-user-attribute.json index 708ea3b8d..a59c7148b 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-increment-user-attribute.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-increment-user-attribute.json @@ -56,7 +56,7 @@ ], "uitl": 60, "oo": false, - "sdk": "8.43.1", + "sdk": "8.44.0", "di": { "p": "arm64", "b": "arm64", diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-log-error.json b/IntegrationTests/wiremock-recordings/mappings/mapping-log-error.json index a9abf0dce..b05aa51ff 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-log-error.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-log-error.json @@ -59,7 +59,7 @@ ], "uitl": 60, "oo": false, - "sdk": "8.43.1", + "sdk": "8.44.0", "di": { "p": "arm64", "b": "arm64", diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-log-event-with-flags.json b/IntegrationTests/wiremock-recordings/mappings/mapping-log-event-with-flags.json index 9fc693187..ae1121787 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-log-event-with-flags.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-log-event-with-flags.json @@ -65,7 +65,7 @@ ], "uitl": 60, "oo": false, - "sdk": "8.43.1", + "sdk": "8.44.0", "di": { "tz": "${json-unit.ignore}", "p": "arm64", diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-log-exception.json b/IntegrationTests/wiremock-recordings/mappings/mapping-log-exception.json index ff2c35b35..5374735fa 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-log-exception.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-log-exception.json @@ -57,7 +57,7 @@ ], "uitl": 60, "oo": false, - "sdk": "8.43.1", + "sdk": "8.44.0", "di": { "tz": "${json-unit.ignore}", "bid": "${json-unit.ignore}", diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-log-idfa.json b/IntegrationTests/wiremock-recordings/mappings/mapping-log-idfa.json index ea07812dd..cd379f199 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-log-idfa.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-log-idfa.json @@ -8,7 +8,7 @@ "equalToJson": { "client_sdk": { "platform": "ios", - "sdk_version": "8.43.1", + "sdk_version": "8.44.0", "sdk_vendor": "mparticle" }, "environment": "development", diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-log-screen.json b/IntegrationTests/wiremock-recordings/mappings/mapping-log-screen.json index 46c198470..1a91a3c93 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-log-screen.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-log-screen.json @@ -54,7 +54,7 @@ ], "uitl": 60, "oo": false, - "sdk": "8.43.1", + "sdk": "8.44.0", "di": { "tz": "${json-unit.ignore}", "bid": "${json-unit.ignore}", diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-rokt-identify.json b/IntegrationTests/wiremock-recordings/mappings/mapping-rokt-identify.json index 43b38eb81..6f28680d1 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-rokt-identify.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-rokt-identify.json @@ -8,7 +8,7 @@ "equalToJson": { "client_sdk": { "platform": "ios", - "sdk_version": "8.43.1", + "sdk_version": "8.44.0", "sdk_vendor": "mparticle" }, "environment": "development", diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-rokt-select-placement.json b/IntegrationTests/wiremock-recordings/mappings/mapping-rokt-select-placement.json index 6bc2ce08f..635e266e3 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-rokt-select-placement.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-rokt-select-placement.json @@ -63,7 +63,7 @@ ], "uitl": 60, "oo": false, - "sdk": "8.43.1", + "sdk": "8.44.0", "di": { "p": "arm64", "tz": "${json-unit.ignore}", diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-set-att-status.json b/IntegrationTests/wiremock-recordings/mappings/mapping-set-att-status.json index 893aded6d..a99fb9479 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-set-att-status.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-set-att-status.json @@ -59,7 +59,7 @@ ], "uitl": 60, "oo": false, - "sdk": "8.43.1", + "sdk": "8.44.0", "di": { "tz": "${json-unit.ignore}", "p": "arm64", diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-set-session-attribute.json b/IntegrationTests/wiremock-recordings/mappings/mapping-set-session-attribute.json index faa70b055..625002923 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-set-session-attribute.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-set-session-attribute.json @@ -58,7 +58,7 @@ ], "uitl": 60, "oo": false, - "sdk": "8.43.1", + "sdk": "8.44.0", "di": { "p": "arm64", "tz": "${json-unit.ignore}", diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-set-user-attributes.json b/IntegrationTests/wiremock-recordings/mappings/mapping-set-user-attributes.json index 7c88fc96a..bbca8b839 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-set-user-attributes.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-set-user-attributes.json @@ -84,7 +84,7 @@ ], "uitl": 60, "oo": false, - "sdk": "8.43.1", + "sdk": "8.44.0", "di": { "p": "arm64", "b": "arm64", diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-timed-event.json b/IntegrationTests/wiremock-recordings/mappings/mapping-timed-event.json index de65f3143..72001d4c7 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-timed-event.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-timed-event.json @@ -59,7 +59,7 @@ ], "uitl": 60, "oo": false, - "sdk": "8.43.1", + "sdk": "8.44.0", "di": { "tz": "${json-unit.ignore}", "bid": "${json-unit.ignore}", diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-v1-identify.json b/IntegrationTests/wiremock-recordings/mappings/mapping-v1-identify.json index b4cca8a69..065e4c42e 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-v1-identify.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-v1-identify.json @@ -8,7 +8,7 @@ "equalToJson": { "client_sdk": { "platform": "ios", - "sdk_version": "8.43.1", + "sdk_version": "8.44.0", "sdk_vendor": "mparticle" }, "environment": "development", diff --git a/IntegrationTests/wiremock-recordings/mappings/mapping-v2-events-log-event.json b/IntegrationTests/wiremock-recordings/mappings/mapping-v2-events-log-event.json index d404599a1..0d1674104 100644 --- a/IntegrationTests/wiremock-recordings/mappings/mapping-v2-events-log-event.json +++ b/IntegrationTests/wiremock-recordings/mappings/mapping-v2-events-log-event.json @@ -120,7 +120,7 @@ ], "uitl": 60, "oo": false, - "sdk": "8.43.1", + "sdk": "8.44.0", "di": { "p": "arm64", "bid": "${json-unit.ignore}", diff --git a/Package.swift b/Package.swift index 966a3edf2..ec3609cbf 100644 --- a/Package.swift +++ b/Package.swift @@ -2,12 +2,12 @@ import PackageDescription -let mParticle_Apple_SDK_URL = "https://static.mparticle.com/sdk/ios/v8.43.1/mParticle_Apple_SDK.xcframework.zip" -let mParticle_Apple_SDK_Checksum = "816b60e4e40d8386e7d0418894a02679ffb95d4bea1e56a84d6535d9204b51eb" +let mParticle_Apple_SDK_URL = "https://static.mparticle.com/sdk/ios/v8.44.0/mParticle_Apple_SDK.xcframework.zip" +let mParticle_Apple_SDK_Checksum = "256df4e388f26d32e94bd4c6583a092d49eb06094a94294dee31eafec9968180" let mParticle_Apple_SDK_NoLocation_URL = - "https://static.mparticle.com/sdk/ios/v8.43.1/mParticle_Apple_SDK_NoLocation.xcframework.zip" -let mParticle_Apple_SDK_NoLocation_Checksum = "a50f0664435c0cdefbe425decff4de720b39eba5263dceb5f4c2d96a50b6eeca" + "https://static.mparticle.com/sdk/ios/v8.44.0/mParticle_Apple_SDK_NoLocation.xcframework.zip" +let mParticle_Apple_SDK_NoLocation_Checksum = "61e6b04442d62de75e19ac6daedc8d49ac9237290982c748ac1a53683f816f31" let package = Package( name: "mParticle-Apple-SDK", diff --git a/mParticle-Apple-SDK.podspec b/mParticle-Apple-SDK.podspec index 45417b3da..ea09fe1e8 100644 --- a/mParticle-Apple-SDK.podspec +++ b/mParticle-Apple-SDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "mParticle-Apple-SDK" - s.version = "8.43.1" + s.version = "8.44.0" s.summary = "mParticle Apple SDK." s.description = <<-DESC diff --git a/mParticle-Apple-SDK/MPConstants.swift b/mParticle-Apple-SDK/MPConstants.swift index 17416037b..33a9b465e 100644 --- a/mParticle-Apple-SDK/MPConstants.swift +++ b/mParticle-Apple-SDK/MPConstants.swift @@ -15,7 +15,7 @@ func MPMilliseconds(timestamp: Double) -> Double { // NOTE: I kept the same naming here for clarity, but we should rename these // after we remove them from the MPIConstants.h file -let kMParticleSDKVersion = "8.43.1" +let kMParticleSDKVersion = "8.44.0" enum MessageKeys { static let kMPMessagesKey = "msgs" diff --git a/mParticle-Apple-SDK/MPIConstants.m b/mParticle-Apple-SDK/MPIConstants.m index 571559d17..567d69295 100644 --- a/mParticle-Apple-SDK/MPIConstants.m +++ b/mParticle-Apple-SDK/MPIConstants.m @@ -1,7 +1,7 @@ #import "MPIConstants.h" // mParticle SDK Version -NSString *const kMParticleSDKVersion = @"8.43.1"; +NSString *const kMParticleSDKVersion = @"8.44.0"; // Message Type (dt) NSString *const kMPMessageTypeKey = @"dt"; diff --git a/mParticle_Apple_SDK.json b/mParticle_Apple_SDK.json index 485f9be55..9bb995bc5 100644 --- a/mParticle_Apple_SDK.json +++ b/mParticle_Apple_SDK.json @@ -126,5 +126,6 @@ "8.42.0": "https://github.com/mParticle/mparticle-apple-sdk/releases/download/v8.42.0/mParticle_Apple_SDK.framework.zip?alt=https://github.com/mParticle/mparticle-apple-sdk/releases/download/v8.42.0/mParticle_Apple_SDK.xcframework.zip", "8.42.1": "https://github.com/mParticle/mparticle-apple-sdk/releases/download/v8.42.1/mParticle_Apple_SDK.framework.zip?alt=https://github.com/mParticle/mparticle-apple-sdk/releases/download/v8.42.1/mParticle_Apple_SDK.xcframework.zip", "8.42.2": "https://github.com/mParticle/mparticle-apple-sdk/releases/download/v8.42.2/mParticle_Apple_SDK.framework.zip?alt=https://github.com/mParticle/mparticle-apple-sdk/releases/download/v8.42.2/mParticle_Apple_SDK.xcframework.zip", - "8.43.1": "https://github.com/mParticle/mparticle-apple-sdk/releases/download/v8.43.1/mParticle_Apple_SDK.framework.zip?alt=https://github.com/mParticle/mparticle-apple-sdk/releases/download/v8.43.1/mParticle_Apple_SDK.xcframework.zip" + "8.43.1": "https://github.com/mParticle/mparticle-apple-sdk/releases/download/v8.43.1/mParticle_Apple_SDK.framework.zip?alt=https://github.com/mParticle/mparticle-apple-sdk/releases/download/v8.43.1/mParticle_Apple_SDK.xcframework.zip", + "8.44.0": "https://github.com/mParticle/mparticle-apple-sdk/releases/download/v8.44.0/mParticle_Apple_SDK.framework.zip?alt=https://github.com/mParticle/mparticle-apple-sdk/releases/download/v8.44.0/mParticle_Apple_SDK.xcframework.zip" } From a4388cb000158ddf63aa591e58fcd66ab4906eea Mon Sep 17 00:00:00 2001 From: Brandon Stalnaker <33703490+BrandonStalnaker@users.noreply.github.com> Date: Wed, 25 Feb 2026 09:34:11 -0500 Subject: [PATCH 3/7] chore: Add MPRoktLayout Implementation to Example App (#598) * chore: Add MPRoktLayout Implementation to Example App --- .../project.pbxproj | 14 +- .../mParticleSwiftExample/ContentView.swift | 248 ++++++++++++++++++ 2 files changed, 255 insertions(+), 7 deletions(-) diff --git a/SwiftExample/mParticleSwiftExample.xcodeproj/project.pbxproj b/SwiftExample/mParticleSwiftExample.xcodeproj/project.pbxproj index 4223af168..1b57d6a7d 100644 --- a/SwiftExample/mParticleSwiftExample.xcodeproj/project.pbxproj +++ b/SwiftExample/mParticleSwiftExample.xcodeproj/project.pbxproj @@ -8,7 +8,7 @@ /* Begin PBXBuildFile section */ 7E4B5EB92F338B9100B61C64 /* mParticle-Apple-SDK in Frameworks */ = {isa = PBXBuildFile; productRef = 7E4B5EB82F338B9100B61C64 /* mParticle-Apple-SDK */; }; - 7E4B5EBC2F338BA500B61C64 /* mParticle-Rokt in Frameworks */ = {isa = PBXBuildFile; productRef = 7E4B5EBB2F338BA500B61C64 /* mParticle-Rokt */; }; + 7ED594AE2F46240D00AB6433 /* mParticle-Rokt in Frameworks */ = {isa = PBXBuildFile; productRef = 7ED594AD2F46240D00AB6433 /* mParticle-Rokt */; }; A10000010000000000000001 /* mParticleSwiftExampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A10000020000000000000001 /* mParticleSwiftExampleApp.swift */; }; A10000010000000000000002 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A10000020000000000000002 /* ContentView.swift */; }; A10000010000000000000003 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A10000020000000000000003 /* Assets.xcassets */; }; @@ -31,7 +31,7 @@ files = ( 7E4B5EB92F338B9100B61C64 /* mParticle-Apple-SDK in Frameworks */, A10000010000000000000004 /* mParticle-Apple-SDK in Frameworks */, - 7E4B5EBC2F338BA500B61C64 /* mParticle-Rokt in Frameworks */, + 7ED594AE2F46240D00AB6433 /* mParticle-Rokt in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -85,7 +85,7 @@ packageProductDependencies = ( A10000030000000000000001 /* mParticle-Apple-SDK */, 7E4B5EB82F338B9100B61C64 /* mParticle-Apple-SDK */, - 7E4B5EBB2F338BA500B61C64 /* mParticle-Rokt */, + 7ED594AD2F46240D00AB6433 /* mParticle-Rokt */, ); productName = mParticleSwiftExample; productReference = A10000020000000000000006 /* mParticleSwiftExample.app */; @@ -117,7 +117,7 @@ mainGroup = A10000050000000000000001; packageReferences = ( 7E4B5EB72F338B9100B61C64 /* XCRemoteSwiftPackageReference "mparticle-apple-sdk" */, - 7E4B5EBA2F338BA500B61C64 /* XCRemoteSwiftPackageReference "mparticle-apple-integration-rokt" */, + 7ED594AC2F46240D00AB6433 /* XCRemoteSwiftPackageReference "mparticle-apple-integration-rokt" */, ); productRefGroup = A10000050000000000000003 /* Products */; projectDirPath = ""; @@ -367,7 +367,7 @@ minimumVersion = 8.4.0; }; }; - 7E4B5EBA2F338BA500B61C64 /* XCRemoteSwiftPackageReference "mparticle-apple-integration-rokt" */ = { + 7ED594AC2F46240D00AB6433 /* XCRemoteSwiftPackageReference "mparticle-apple-integration-rokt" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/mparticle-integrations/mparticle-apple-integration-rokt.git"; requirement = { @@ -383,9 +383,9 @@ package = 7E4B5EB72F338B9100B61C64 /* XCRemoteSwiftPackageReference "mparticle-apple-sdk" */; productName = "mParticle-Apple-SDK"; }; - 7E4B5EBB2F338BA500B61C64 /* mParticle-Rokt */ = { + 7ED594AD2F46240D00AB6433 /* mParticle-Rokt */ = { isa = XCSwiftPackageProductDependency; - package = 7E4B5EBA2F338BA500B61C64 /* XCRemoteSwiftPackageReference "mparticle-apple-integration-rokt" */; + package = 7ED594AC2F46240D00AB6433 /* XCRemoteSwiftPackageReference "mparticle-apple-integration-rokt" */; productName = "mParticle-Rokt"; }; A10000030000000000000001 /* mParticle-Apple-SDK */ = { diff --git a/SwiftExample/mParticleSwiftExample/ContentView.swift b/SwiftExample/mParticleSwiftExample/ContentView.swift index e0e6db1b7..707ae2ecc 100644 --- a/SwiftExample/mParticleSwiftExample/ContentView.swift +++ b/SwiftExample/mParticleSwiftExample/ContentView.swift @@ -1,6 +1,8 @@ // swiftlint:disable file_length import SwiftUI import mParticle_Apple_SDK +import mParticle_Rokt_Swift +import Rokt_Widget import AdSupport import AppTrackingTransparency @@ -95,6 +97,13 @@ struct ContentView: View { title: "Display Rokt Overlay (auto close)", action: selectOverlayPlacementAutoClose ) + ActionButton( + title: "Display Rokt with Event Subscription", + action: selectPlacementWithEventSubscription + ) + NavigationLink("MPRoktLayout SwiftUI Example") { + RoktLayoutExampleView() + } } } .listStyle(InsetGroupedListStyle()) @@ -202,6 +211,175 @@ struct RoktEmbeddedViewWrapper: UIViewRepresentable { } } +// MARK: - MPRoktLayout SwiftUI Example + +struct RoktLayoutExampleView: View { + @State private var sdkTriggered = false + @State private var eventLog: [String] = [] + + let attributes: [String: String] = [ + "email": "j.smith@example.com", + "firstname": "Jenny", + "lastname": "Smith", + "billingzipcode": "07762", + "confirmationref": "54321", + "sandbox": "true", + "mobile": "(555)867-5309" + ] + + var body: some View { + ScrollView { + VStack(alignment: .leading, spacing: 16) { + Text("MPRoktLayout Example") + .font(.title2) + .fontWeight(.bold) + .padding(.horizontal) + + Text("This demonstrates the SwiftUI-native MPRoktLayout component for embedding Rokt placements declaratively.") + .font(.subheadline) + .foregroundColor(.secondary) + .padding(.horizontal) + + // Trigger button + Button { + sdkTriggered = true + eventLog.append("[\(formattedTime())] Triggered placement") + } label: { + Text(sdkTriggered ? "Placement Triggered" : "Trigger Rokt Placement") + .frame(maxWidth: .infinity) + .padding() + .background(sdkTriggered ? Color.gray : Color.blue) + .foregroundColor(.white) + .cornerRadius(10) + } + .disabled(sdkTriggered) + .padding(.horizontal) + + // Reset button + if sdkTriggered { + Button { + sdkTriggered = false + eventLog.append("[\(formattedTime())] Reset placement") + } label: { + Text("Reset") + .frame(maxWidth: .infinity) + .padding() + .background(Color.orange) + .foregroundColor(.white) + .cornerRadius(10) + } + .padding(.horizontal) + } + + // Rokt Layout - Embedded Placement + if sdkTriggered { + VStack(alignment: .leading, spacing: 8) { + Text("Embedded Placement") + .font(.headline) + .padding(.horizontal) + + MPRoktLayout( + sdkTriggered: $sdkTriggered, + viewName: "RoktExperience", + locationName: "RoktEmbedded1", + attributes: attributes, + config: createRoktConfig(), + onEvent: { roktEvent in + handleRoktEvent(roktEvent) + } + ).roktLayout + .padding(.horizontal) + } + } + + // Event Log + VStack(alignment: .leading, spacing: 8) { + Text("Event Log") + .font(.headline) + .padding(.horizontal) + + if eventLog.isEmpty { + Text("No events yet. Trigger the placement to see events.") + .font(.caption) + .foregroundColor(.secondary) + .padding(.horizontal) + } else { + ForEach(eventLog.reversed(), id: \.self) { event in + Text(event) + .font(.system(.caption, design: .monospaced)) + .padding(.horizontal) + } + } + } + .padding(.vertical) + .background(Color(.systemGray6)) + .cornerRadius(10) + .padding(.horizontal) + + Spacer() + } + .padding(.vertical) + } + .navigationTitle("MPRoktLayout") + .navigationBarTitleDisplayMode(.inline) + } + + private func createRoktConfig() -> RoktConfig { + return RoktConfig.Builder().build() + } + + private func handleRoktEvent(_ event: RoktEvent) { + let timestamp = formattedTime() + + switch event { + case is RoktEvent.ShowLoadingIndicator: + eventLog.append("[\(timestamp)] Show Loading Indicator") + + case is RoktEvent.HideLoadingIndicator: + eventLog.append("[\(timestamp)] Hide Loading Indicator") + + case let placementReady as RoktEvent.PlacementReady: + eventLog.append("[\(timestamp)] Placement Ready - ID: \(placementReady.placementId ?? "unknown")") + + case let placementInteractive as RoktEvent.PlacementInteractive: + eventLog.append("[\(timestamp)] Placement Interactive - ID: \(placementInteractive.placementId ?? "unknown")") + + case let offerEngagement as RoktEvent.OfferEngagement: + eventLog.append("[\(timestamp)] Offer Engagement - ID: \(offerEngagement.placementId ?? "unknown")") + + case let positiveEngagement as RoktEvent.PositiveEngagement: + eventLog.append("[\(timestamp)] Positive Engagement - ID: \(positiveEngagement.placementId ?? "unknown")") + + case let firstPositiveEngagement as RoktEvent.FirstPositiveEngagement: + eventLog.append("[\(timestamp)] First Positive Engagement - ID: \(firstPositiveEngagement.placementId ?? "unknown")") + + case let openUrl as RoktEvent.OpenUrl: + eventLog.append("[\(timestamp)] Open URL - \(openUrl.url)") + + case let placementClosed as RoktEvent.PlacementClosed: + eventLog.append("[\(timestamp)] Placement Closed - ID: \(placementClosed.placementId ?? "unknown")") + + case let placementCompleted as RoktEvent.PlacementCompleted: + eventLog.append("[\(timestamp)] Placement Completed - ID: \(placementCompleted.placementId ?? "unknown")") + + case let placementFailure as RoktEvent.PlacementFailure: + eventLog.append("[\(timestamp)] Placement Failure - ID: \(placementFailure.placementId ?? "unknown")") + + case let cartItem as RoktEvent.CartItemInstantPurchase: + eventLog.append("[\(timestamp)] Cart Item Purchase - \(cartItem.name ?? "unknown")") + + default: + eventLog.append("[\(timestamp)] Event: \(type(of: event))") + } + } + + private func formattedTime() -> String { + let formatter = DateFormatter() + formatter.dateFormat = "HH:mm:ss" + return formatter.string(from: Date()) + } +} + // MARK: - mParticle Actions func logSimpleEvent() { @@ -718,6 +896,76 @@ func selectOverlayPlacementAutoClose() { } } +func selectPlacementWithEventSubscription() { + let customAttributes: [String: String] = [ + "email": "j.smit@example.com", + "firstname": "Jenny", + "lastname": "Smith", + "sandbox": "true", + "mobile": "(555)867-5309" + ] + + let placementIdentifier = "RoktLayout" + + // Subscribe to Rokt events for this placement + MParticle.sharedInstance().rokt.events(placementIdentifier) { event in + switch event { + case let initComplete as MPRoktEvent.MPRoktInitComplete: + print("Rokt Init Complete - Success: \(initComplete.success)") + + case is MPRoktEvent.MPRoktShowLoadingIndicator: + print("Rokt: Show Loading Indicator") + + case is MPRoktEvent.MPRoktHideLoadingIndicator: + print("Rokt: Hide Loading Indicator") + + case let placementReady as MPRoktEvent.MPRoktPlacementReady: + print("Rokt Placement Ready - ID: \(placementReady.placementId ?? "unknown")") + + case let placementInteractive as MPRoktEvent.MPRoktPlacementInteractive: + print("Rokt Placement Interactive - ID: \(placementInteractive.placementId ?? "unknown")") + + case let offerEngagement as MPRoktEvent.MPRoktOfferEngagement: + print("Rokt Offer Engagement - ID: \(offerEngagement.placementId ?? "unknown")") + + case let positiveEngagement as MPRoktEvent.MPRoktPositiveEngagement: + print("Rokt Positive Engagement - ID: \(positiveEngagement.placementId ?? "unknown")") + + case let firstPositiveEngagement as MPRoktEvent.MPRoktFirstPositiveEngagement: + print("Rokt First Positive Engagement - ID: \(firstPositiveEngagement.placementId ?? "unknown")") + + case let openUrl as MPRoktEvent.MPRoktOpenUrl: + print("Rokt Open URL - ID: \(openUrl.placementId ?? "unknown"), URL: \(openUrl.url)") + + case let placementClosed as MPRoktEvent.MPRoktPlacementClosed: + print("Rokt Placement Closed - ID: \(placementClosed.placementId ?? "unknown")") + + case let placementCompleted as MPRoktEvent.MPRoktPlacementCompleted: + print("Rokt Placement Completed - ID: \(placementCompleted.placementId ?? "unknown")") + + case let placementFailure as MPRoktEvent.MPRoktPlacementFailure: + print("Rokt Placement Failure - ID: \(placementFailure.placementId ?? "unknown")") + + case let cartItem as MPRoktEvent.MPRoktCartItemInstantPurchase: + print("Rokt Cart Item Instant Purchase:") + print(" - Placement ID: \(cartItem.placementId)") + print(" - Catalog Item ID: \(cartItem.catalogItemId)") + print(" - Cart Item ID: \(cartItem.cartItemId)") + print(" - Name: \(cartItem.name ?? "unknown")") + print(" - Currency: \(cartItem.currency)") + print(" - Unit Price: \(cartItem.unitPrice ?? 0)") + print(" - Total Price: \(cartItem.totalPrice ?? 0)") + print(" - Quantity: \(cartItem.quantity ?? 0)") + + default: + print("Rokt: Unknown event type - \(type(of: event))") + } + } + + // Select the placement (this will trigger events) + MParticle.sharedInstance().rokt.selectPlacements(placementIdentifier, attributes: customAttributes) +} + #Preview { ContentView() } From 65bf05eee6950335f7f141c79ee26cb7e3985926 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Mar 2026 11:24:42 -0500 Subject: [PATCH 4/7] chore: bump futureware-tech/simulator-action from 4 to 5 (#643) Bumps [futureware-tech/simulator-action](https://github.com/futureware-tech/simulator-action) from 4 to 5. - [Release notes](https://github.com/futureware-tech/simulator-action/releases) - [Changelog](https://github.com/futureware-tech/simulator-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/futureware-tech/simulator-action/compare/v4...v5) --- updated-dependencies: - dependency-name: futureware-tech/simulator-action dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-secondary-platforms.yml | 2 +- .github/workflows/native-tests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-secondary-platforms.yml b/.github/workflows/build-secondary-platforms.yml index 0b8865c89..a76c1a8c9 100644 --- a/.github/workflows/build-secondary-platforms.yml +++ b/.github/workflows/build-secondary-platforms.yml @@ -23,7 +23,7 @@ jobs: xcode-version: ${{ env.XCODE_VERSION }} - name: Setup specified simulator - uses: futureware-tech/simulator-action@v4 + uses: futureware-tech/simulator-action@v5 id: simulator with: model: iPhone 16 Pro diff --git a/.github/workflows/native-tests.yml b/.github/workflows/native-tests.yml index 7edfbf238..c59f4ef6f 100644 --- a/.github/workflows/native-tests.yml +++ b/.github/workflows/native-tests.yml @@ -32,7 +32,7 @@ jobs: xcode-version: ${{ env.XCODE_VERSION }} - name: Setup specified simulator - uses: futureware-tech/simulator-action@v4 + uses: futureware-tech/simulator-action@v5 id: simulator with: model: ${{ matrix.device }} From 06e7254fbfae976e3c6c53220fc38adf64aaa983 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 10:16:26 -0500 Subject: [PATCH 5/7] chore: bump actions/upload-artifact from 6 to 7 (#642) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/cross-platform-tests.yml | 2 +- .github/workflows/integration-tests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cross-platform-tests.yml b/.github/workflows/cross-platform-tests.yml index b93578acb..2ade257ed 100644 --- a/.github/workflows/cross-platform-tests.yml +++ b/.github/workflows/cross-platform-tests.yml @@ -40,7 +40,7 @@ jobs: run: ./gradlew runIos - name: Archive Test Results if: always() - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: ios-test-results path: Users/runner/Library/Developer/Xcode/DerivedData diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 7af9eeda9..5fa4d4554 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -95,7 +95,7 @@ jobs: - name: Upload artifacts on failure if: failure() - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: integration-test-artifacts path: ${{ env.WORKING_DIRECTORY }}/artifacts/ From cb1e126c4fc9f3df48bebb23d6bb913fe6b77f26 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Mar 2026 10:39:27 -0500 Subject: [PATCH 6/7] chore: bump fast-xml-parser from 4.5.0 to 4.5.4 in /RNExample (#645) Bumps [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) from 4.5.0 to 4.5.4. - [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases) - [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v4.5.0...v4.5.4) --- updated-dependencies: - dependency-name: fast-xml-parser dependency-version: 4.5.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- RNExample/package-lock.json | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/RNExample/package-lock.json b/RNExample/package-lock.json index fa4f77d0e..49b8f36a9 100644 --- a/RNExample/package-lock.json +++ b/RNExample/package-lock.json @@ -6382,18 +6382,14 @@ "license": "MIT" }, "node_modules/fast-xml-parser": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.0.tgz", - "integrity": "sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.4.tgz", + "integrity": "sha512-jE8ugADnYOBsu1uaoayVl1tVKAMNOXyjwvv2U6udEA2ORBhDooJDWoGxTkhd4Qn4yh59JVVt/pKXtjPwx9OguQ==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/NaturalIntelligence" - }, - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" } ], "license": "MIT", From 84ad08757b5c845dfefe9b9e1bef2655b5e8c9ed Mon Sep 17 00:00:00 2001 From: Brandon Stalnaker <33703490+BrandonStalnaker@users.noreply.github.com> Date: Mon, 9 Mar 2026 12:38:21 -0400 Subject: [PATCH 7/7] fix: Remove Outdated previousSessionSuccessfullyClosed Logic (#655) --- .../ObjCTests/MPBackendControllerTests.m | 6 +-- mParticle-Apple-SDK/MPBackendController.m | 47 ------------------- mParticle-Apple-SDK/MPIConstants.h | 2 - mParticle-Apple-SDK/MPIConstants.m | 2 - 4 files changed, 2 insertions(+), 55 deletions(-) diff --git a/UnitTests/ObjCTests/MPBackendControllerTests.m b/UnitTests/ObjCTests/MPBackendControllerTests.m index b24b63567..537f17289 100644 --- a/UnitTests/ObjCTests/MPBackendControllerTests.m +++ b/UnitTests/ObjCTests/MPBackendControllerTests.m @@ -77,8 +77,6 @@ - (void)handleApplicationDidBecomeActive:(NSNotification *)notification; - (void)logRemoteNotificationWithNotificationController:(MPNotificationController_PRIVATE *const)notificationController; - (void)parseConfigResponse:(NSDictionary *)configurationDictionary; - (void)parseResponseHeader:(NSDictionary *)responseDictionary session:(MPSession *)session; -- (NSNumber *)previousSessionSuccessfullyClosed; -- (void)setPreviousSessionSuccessfullyClosed:(NSNumber *)previousSessionSuccessfullyClosed; - (void)processOpenSessionsEndingCurrent:(BOOL)endCurrentSession completionHandler:(dispatch_block_t)completionHandler; - (void)resetUserIdentitiesFirstTimeUseFlag; - (void)saveMessage:(MPMessage *)message updateSession:(BOOL)updateSession; @@ -125,10 +123,10 @@ @implementation MPBackendControllerTests - (void)setUp { [super setUp]; - + [MPPersistenceController_PRIVATE setMpid:@1]; [MParticle sharedInstance].persistenceController = [[MPPersistenceController_PRIVATE alloc] init]; - + // Must read messageQueue AFTER [MParticle sharedInstance] triggers singleton // recreation, otherwise we get the old executor's queue. messageQueue = [MParticle messageQueue]; diff --git a/mParticle-Apple-SDK/MPBackendController.m b/mParticle-Apple-SDK/MPBackendController.m index b674e4e72..02e3cef04 100644 --- a/mParticle-Apple-SDK/MPBackendController.m +++ b/mParticle-Apple-SDK/MPBackendController.m @@ -324,50 +324,6 @@ - (void)logUserIdentityChange:(MPUserIdentityChange_PRIVATE *)userIdentityChange [self saveMessage:message updateSession:YES]; } -- (NSNumber *)previousSessionSuccessfullyClosed { - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSString *stateMachineDirectoryPath = STATE_MACHINE_DIRECTORY_PATH; - NSString *previousSessionStateFile = [stateMachineDirectoryPath stringByAppendingPathComponent:kMPPreviousSessionStateFileName]; - NSNumber *previousSessionSuccessfullyClosed = nil; - if ([fileManager fileExistsAtPath:previousSessionStateFile]) { - NSDictionary *previousSessionStateDictionary = [NSDictionary dictionaryWithContentsOfFile:previousSessionStateFile]; - previousSessionSuccessfullyClosed = previousSessionStateDictionary[kMPASTPreviousSessionSuccessfullyClosedKey]; - } - - if (previousSessionSuccessfullyClosed == nil) { - previousSessionSuccessfullyClosed = @YES; - } - - return previousSessionSuccessfullyClosed; -} - -- (void)setPreviousSessionSuccessfullyClosed:(NSNumber *)previousSessionSuccessfullyClosed { - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSString *stateMachineDirectoryPath = STATE_MACHINE_DIRECTORY_PATH; - NSString *previousSessionStateFile = [stateMachineDirectoryPath stringByAppendingPathComponent:kMPPreviousSessionStateFileName]; - NSDictionary *previousSessionStateDictionary = @{kMPASTPreviousSessionSuccessfullyClosedKey:previousSessionSuccessfullyClosed}; - - @try { - if (![fileManager fileExistsAtPath:stateMachineDirectoryPath]) { - NSError *dirError = nil; - [fileManager createDirectoryAtPath:stateMachineDirectoryPath withIntermediateDirectories:YES attributes:nil error:&dirError]; - if (dirError) { - MPILogError(@"Failed to create state machine directory: %@", dirError); - return; - } - } else if ([fileManager fileExistsAtPath:previousSessionStateFile]) { - [fileManager removeItemAtPath:previousSessionStateFile error:nil]; - } - - BOOL success = [previousSessionStateDictionary writeToFile:previousSessionStateFile atomically:YES]; - if (!success) { - MPILogError(@"Failed to write previous session state to file"); - } - } @catch (NSException *exception) { - MPILogError(@"Exception writing previous session state: %@", exception); - } -} - - (void)processDidFinishLaunching:(NSNotification *)notification { NSString *astType = kMPASTInitKey; NSMutableDictionary *messageInfo = [[NSMutableDictionary alloc] initWithCapacity:3]; @@ -384,8 +340,6 @@ - (void)processDidFinishLaunching:(NSNotification *)notification { isInstallOrUpgrade = YES; } - messageInfo[kMPASTPreviousSessionSuccessfullyClosedKey] = [self previousSessionSuccessfullyClosed]; - NSDictionary *userInfo = [notification userInfo]; if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) { @@ -2136,7 +2090,6 @@ - (void)handleApplicationDidEnterBackground:(NSNotification *)notification { self.timeAppWentToBackgroundInCurrentSession = currentTime; self.timeOfLastEventInBackground = currentTime; - [self setPreviousSessionSuccessfullyClosed:@YES]; [self cleanUp]; MPMessageBuilder *messageBuilder = [[MPMessageBuilder alloc] initWithMessageType:MPMessageTypeAppStateTransition diff --git a/mParticle-Apple-SDK/MPIConstants.h b/mParticle-Apple-SDK/MPIConstants.h index 6a3a55167..1059ed669 100644 --- a/mParticle-Apple-SDK/MPIConstants.h +++ b/mParticle-Apple-SDK/MPIConstants.h @@ -186,7 +186,6 @@ extern NSString * _Nonnull const kMPUploadIntervalKey; extern NSString * _Nonnull const kMPPreviousSessionLengthKey; extern NSString * _Nonnull const kMPLifeTimeValueKey; extern NSString * _Nonnull const kMPIncreasedLifeTimeValueKey; -extern NSString * _Nonnull const kMPPreviousSessionStateFileName; extern NSString * _Nonnull const kMPHTTPMethodPost; extern NSString * _Nonnull const kMPHTTPMethodGet; extern NSString * _Nonnull const kMPPreviousSessionIdKey; @@ -365,7 +364,6 @@ extern NSString * _Nonnull const kMPASTBackgroundKey; extern NSString * _Nonnull const kMPASTForegroundKey; extern NSString * _Nonnull const kMPASTIsFirstRunKey; extern NSString * _Nonnull const kMPASTIsUpgradeKey; -extern NSString * _Nonnull const kMPASTPreviousSessionSuccessfullyClosedKey; // Network performance extern NSString * _Nonnull const kMPNetworkPerformanceMeasurementNotification; diff --git a/mParticle-Apple-SDK/MPIConstants.m b/mParticle-Apple-SDK/MPIConstants.m index 567d69295..ecefbcece 100644 --- a/mParticle-Apple-SDK/MPIConstants.m +++ b/mParticle-Apple-SDK/MPIConstants.m @@ -139,7 +139,6 @@ NSString *const kMPPreviousSessionLengthKey = @"psl"; NSString *const kMPLifeTimeValueKey = @"ltv"; NSString *const kMPIncreasedLifeTimeValueKey = @"iltv"; -NSString *const kMPPreviousSessionStateFileName = @"PreviousSessionState.dic"; NSString *const kMPHTTPMethodPost = @"POST"; NSString *const kMPHTTPMethodGet = @"GET"; NSString *const kMPPreviousSessionIdKey = @"pid"; @@ -310,7 +309,6 @@ NSString *const kMPASTForegroundKey = @"app_fore"; NSString *const kMPASTIsFirstRunKey = @"ifr"; NSString *const kMPASTIsUpgradeKey = @"iu"; -NSString *const kMPASTPreviousSessionSuccessfullyClosedKey = @"sc"; // Network performance NSString *const kMPNetworkPerformanceMeasurementNotification = @"MPNetworkPerformanceMeasurement";