From 6e9952c2752d3dfb32bc6d2a9f874a72a8c94714 Mon Sep 17 00:00:00 2001 From: Martin Cardozo Date: Thu, 15 Jan 2026 15:35:26 -0300 Subject: [PATCH 1/7] Events pipeline adapted --- Split/Api/DefaultSplitClient.swift | 2 +- Split/Api/SplitClient.swift | 2 +- Split/Events/SplitEventActionTask.swift | 17 ++++--- Split/Events/SplitMetadata.swift | 2 +- SplitTests/SplitEventsManagerTest.swift | 65 ++++++++++++++++++++++++- 5 files changed, 76 insertions(+), 12 deletions(-) diff --git a/Split/Api/DefaultSplitClient.swift b/Split/Api/DefaultSplitClient.swift index d721f254b..16d92ac59 100644 --- a/Split/Api/DefaultSplitClient.swift +++ b/Split/Api/DefaultSplitClient.swift @@ -69,7 +69,7 @@ extension DefaultSplitClient { guard let factory = clientManager?.splitFactory else { return } - + let task = SplitEventActionTask(action: action, event: event, runInBackground: runInBackground, factory: factory, diff --git a/Split/Api/SplitClient.swift b/Split/Api/SplitClient.swift index 56b8ba1a5..adbdb9919 100644 --- a/Split/Api/SplitClient.swift +++ b/Split/Api/SplitClient.swift @@ -9,7 +9,7 @@ import Foundation public typealias SplitAction = () -> Void -public typealias SplitActionWithMetadata = (EventMetadata) -> Void +public typealias SplitActionWithMetadata = (T) -> Void @objc public protocol SplitClient { diff --git a/Split/Events/SplitEventActionTask.swift b/Split/Events/SplitEventActionTask.swift index 2d0e48a3c..da034350e 100644 --- a/Split/Events/SplitEventActionTask.swift +++ b/Split/Events/SplitEventActionTask.swift @@ -5,18 +5,21 @@ import Foundation class SplitEventActionTask: SplitEventTask, @unchecked Sendable { private var eventHandler: SplitAction? - private var eventHandlerWithMetadata: SplitActionWithMetadata? + private var eventHandlerWithMetadata: SplitActionWithMetadata? private var queue: DispatchQueue? var event: SplitEvent var runInBackground: Bool = false var factory: SplitFactory - init(action: @escaping SplitActionWithMetadata, event: SplitEvent, runInBackground: Bool = false, factory: SplitFactory, queue: DispatchQueue? = nil) { - self.eventHandlerWithMetadata = action - self.event = event - self.runInBackground = runInBackground - self.queue = queue - self.factory = factory + init(action: @escaping SplitActionWithMetadata, event: SplitEvent, runInBackground: Bool = false, factory: SplitFactory, queue: DispatchQueue? = nil) { + self.eventHandlerWithMetadata = { metadata in + guard let typed = metadata as? T else { return } + action(typed) + } + self.event = event + self.runInBackground = runInBackground + self.queue = queue + self.factory = factory } init(action: @escaping SplitAction, event: SplitEvent, runInBackground: Bool = false, factory: SplitFactory, queue: DispatchQueue? = nil) { diff --git a/Split/Events/SplitMetadata.swift b/Split/Events/SplitMetadata.swift index afe38623b..efa6a638d 100644 --- a/Split/Events/SplitMetadata.swift +++ b/Split/Events/SplitMetadata.swift @@ -2,7 +2,7 @@ import Foundation -@objc public protocol EventMetadata: Sendable {} +@objc public protocol EventMetadata: Sendable, NSObjectProtocol {} // MARK: UPDATE /// Represents the type of SDK update that triggered a metadata callback. diff --git a/SplitTests/SplitEventsManagerTest.swift b/SplitTests/SplitEventsManagerTest.swift index 3eff3ebd7..1b3eccfa5 100644 --- a/SplitTests/SplitEventsManagerTest.swift +++ b/SplitTests/SplitEventsManagerTest.swift @@ -306,13 +306,74 @@ class SplitEventsManagerTest: XCTestCase, @unchecked Sendable { eventManager.stop() } + func testSdkReadyWithMetadata() { + let taskExp = XCTestExpectation() + + let timestamp: Int64 = 1000 + let freshInstall = true + + let metadata = SdkReadyMetadata(lastUpdateTimestamp: timestamp, isInitialCacheLoad: freshInstall) + + let handler: SplitActionWithMetadata = { handlerMetadata in + XCTAssertEqual(handlerMetadata.lastUpdateTimestamp, timestamp) + XCTAssertEqual(handlerMetadata.isInitialCacheLoad, freshInstall) + taskExp.fulfill() + } + let task = SplitEventActionTask(action: handler, + event: .sdkReady, + runInBackground: false, + factory: SplitFactoryStub(apiKey: IntegrationHelper.dummyApiKey), + queue: nil) + + // Run & test + task.run(metadata) + wait(for: [taskExp], timeout: 1) + } + + func testSdkUpdateWithMetadata() { + let taskExp = XCTestExpectation() + + let type: SdkUpdateMetadataType = .FLAGS_UPDATE + let names = ["Flag1", "FLAG2"] + + let metadata = SdkUpdateMetadata(type: type, names: names) + + let handler: SplitActionWithMetadata = { handlerMetadata in + XCTAssertEqual(handlerMetadata.type, type) + XCTAssertEqual(handlerMetadata.names, names) + taskExp.fulfill() + } + let task = SplitEventActionTask(action: handler, event: .sdkReady, runInBackground: false, factory: SplitFactoryStub(apiKey: IntegrationHelper.dummyApiKey), queue: nil) + + // Run & test + task.run(metadata) + wait(for: [taskExp], timeout: 1) + } + + func testSdkReadyFromCacheWithMetadata() { + let taskExp = XCTestExpectation() + + let freshInstall = true + let metadata = SdkReadyFromCacheMetadata(isInitialCacheLoad: freshInstall) + + let handler: SplitActionWithMetadata = { handlerMetadata in + XCTAssertEqual(handlerMetadata.isInitialCacheLoad, freshInstall) + taskExp.fulfill() + } + let task = SplitEventActionTask(action: handler, event: .sdkReady, runInBackground: false, factory: SplitFactoryStub(apiKey: IntegrationHelper.dummyApiKey), queue: nil) + + // Run & test + task.run(metadata) + wait(for: [taskExp], timeout: 1) + } + // MARK: Helpers func currentTimestamp() -> Int { return Int(Date().unixTimestamp()) } func sdkTask(exp: XCTestExpectation) -> TestTask { - return TestTask(exp: exp) + TestTask(exp: exp) } } @@ -321,7 +382,7 @@ class TestTask: SplitEventActionTask, @unchecked Sendable { var taskTriggered = false let label: String var exp: XCTestExpectation? - init(exp: XCTestExpectation?, label: String = "", action: SplitActionWithMetadata? = nil, metadata: EventMetadata? = nil) { + init(exp: XCTestExpectation?, label: String = "", action: SplitActionWithMetadata? = nil, metadata: EventMetadata? = nil) { self.exp = exp self.label = label super.init(action: action ?? { _ in }, event: .sdkReady, factory: SplitFactoryStub(apiKey: IntegrationHelper.dummyApiKey)) From c59bc705653e34445d1df74c5d4a228bdce95cbc Mon Sep 17 00:00:00 2001 From: Martin Cardozo Date: Thu, 15 Jan 2026 15:37:58 -0300 Subject: [PATCH 2/7] Space removed --- Split/Api/DefaultSplitClient.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Split/Api/DefaultSplitClient.swift b/Split/Api/DefaultSplitClient.swift index 16d92ac59..d721f254b 100644 --- a/Split/Api/DefaultSplitClient.swift +++ b/Split/Api/DefaultSplitClient.swift @@ -69,7 +69,7 @@ extension DefaultSplitClient { guard let factory = clientManager?.splitFactory else { return } - + let task = SplitEventActionTask(action: action, event: event, runInBackground: runInBackground, factory: factory, From 0474de2e2c9cc4f6135efc6d3e28a1cd7ac6aba5 Mon Sep 17 00:00:00 2001 From: Martin Cardozo Date: Fri, 16 Jan 2026 10:12:36 -0300 Subject: [PATCH 3/7] Clients now expose the listeners --- Split/Api/DefaultSplitClient.swift | 22 +++++++++++++++++++ Split/Api/FailHelpers.swift | 8 +++++++ Split/Api/LocalhostSplitClient.swift | 9 ++++++++ Split/Api/SplitClient.swift | 8 +++++++ Split/Events/SplitEventActionTask.swift | 2 +- SplitTests/Fake/InternalSplitClientStub.swift | 17 ++++++++------ SplitTests/Fake/SplitClientStub.swift | 6 +++++ 7 files changed, 64 insertions(+), 8 deletions(-) diff --git a/Split/Api/DefaultSplitClient.swift b/Split/Api/DefaultSplitClient.swift index d721f254b..64914f760 100644 --- a/Split/Api/DefaultSplitClient.swift +++ b/Split/Api/DefaultSplitClient.swift @@ -87,6 +87,28 @@ extension DefaultSplitClient { } eventsManager.register(event: event, task: task) } + + // MARK: Events Listeners with Medatadata + @objc(onSdkReady:) + public func onSdkReady(action: @escaping (SdkReadyMetadata) -> Void) { + registerEvent(.sdkReady, action: action) + } + + @objc(onSdkReadyFromCache:) + public func onSdkReadyFromCache(action: @escaping (SdkReadyFromCacheMetadata) -> Void) { + registerEvent(.sdkReadyFromCache, action: action) + } + + @objc(onSdkUpdate:) + public func onSdkUpdate(action: @escaping (SdkUpdateMetadata) -> Void) { + registerEvent(.sdkUpdated, action: action) + } + + private func registerEvent(_ event: SplitEvent, action: @escaping (T) -> Void) { + guard let factory = clientManager?.splitFactory else { return } + let task = SplitEventActionTask(action: action, event: event, runInBackground: true, factory: factory, queue: nil) + eventsManager.register(event: event, task: task) + } } // MARK: Treatment / Evaluation diff --git a/Split/Api/FailHelpers.swift b/Split/Api/FailHelpers.swift index c668fa5e1..76ec664c2 100644 --- a/Split/Api/FailHelpers.swift +++ b/Split/Api/FailHelpers.swift @@ -53,11 +53,19 @@ class FailedClient: SplitClient { [:] } + // MARK: Events func on(event: SplitEvent, execute action: @escaping SplitAction) {} func on(event: SplitEvent, runInBackground: Bool, execute action: @escaping SplitAction) {} func on(event: SplitEvent, queue: DispatchQueue, execute action: @escaping SplitAction) {} + + // MARK: Events with Metadata + func onSdkReady(action: @escaping (SdkReadyMetadata) -> Void) {} + + func onSdkReadyFromCache(action: @escaping (SdkReadyFromCacheMetadata) -> Void) {} + + func onSdkUpdate(action: @escaping (SdkUpdateMetadata) -> Void) {} func track(trafficType: String, eventType: String) -> Bool { false diff --git a/Split/Api/LocalhostSplitClient.swift b/Split/Api/LocalhostSplitClient.swift index 607e761ac..ee3b973a3 100644 --- a/Split/Api/LocalhostSplitClient.swift +++ b/Split/Api/LocalhostSplitClient.swift @@ -117,6 +117,7 @@ public final class LocalhostSplitClient: NSObject, SplitClient { return results } + // MARK: Events public func on(event: SplitEvent, runInBackground: Bool, execute action: @escaping SplitAction) { on(event: event, runInBackground: runInBackground, queue: nil, execute: action) } @@ -140,7 +141,15 @@ public final class LocalhostSplitClient: NSObject, SplitClient { eventsManager.register(event: event, task: task) } } + + // MARK: Events with Metadata + public func onSdkReady(action: @escaping (SdkReadyMetadata) -> Void) {} + + public func onSdkReadyFromCache(action: @escaping (SdkReadyFromCacheMetadata) -> Void) {} + + public func onSdkUpdate(action: @escaping (SdkUpdateMetadata) -> Void) {} + // MARK: Track public func track(trafficType: String, eventType: String) -> Bool { true } diff --git a/Split/Api/SplitClient.swift b/Split/Api/SplitClient.swift index adbdb9919..c4ad66fdb 100644 --- a/Split/Api/SplitClient.swift +++ b/Split/Api/SplitClient.swift @@ -37,6 +37,14 @@ public typealias SplitActionWithMetadata = (T) -> Void func on(event: SplitEvent, execute action: @escaping SplitAction) func on(event: SplitEvent, runInBackground: Bool, execute action: @escaping SplitAction) func on(event: SplitEvent, queue: DispatchQueue, execute action: @escaping SplitAction) + + // MARK: Events with Metadata + @objc(onSdkReady:) + func onSdkReady(action: @escaping (SdkReadyMetadata) -> Void) + @objc(onSdkReadyFromCache:) + func onSdkReadyFromCache(action: @escaping (SdkReadyFromCacheMetadata) -> Void) + @objc(onSdkUpdate:) + func onSdkUpdate(action: @escaping (SdkUpdateMetadata) -> Void) // MARK: Track feature func track(trafficType: String, eventType: String) -> Bool diff --git a/Split/Events/SplitEventActionTask.swift b/Split/Events/SplitEventActionTask.swift index da034350e..4d64ed522 100644 --- a/Split/Events/SplitEventActionTask.swift +++ b/Split/Events/SplitEventActionTask.swift @@ -13,7 +13,7 @@ class SplitEventActionTask: SplitEventTask, @unchecked Sendable { init(action: @escaping SplitActionWithMetadata, event: SplitEvent, runInBackground: Bool = false, factory: SplitFactory, queue: DispatchQueue? = nil) { self.eventHandlerWithMetadata = { metadata in - guard let typed = metadata as? T else { return } + guard let typed = metadata as? T else { return } action(typed) } self.event = event diff --git a/SplitTests/Fake/InternalSplitClientStub.swift b/SplitTests/Fake/InternalSplitClientStub.swift index 7992e09bd..08c4c5cbb 100644 --- a/SplitTests/Fake/InternalSplitClientStub.swift +++ b/SplitTests/Fake/InternalSplitClientStub.swift @@ -10,7 +10,7 @@ import Foundation @testable import Split class InternalSplitClientStub: InternalSplitClient, @unchecked Sendable { - + var splitsStorage: SplitsStorage? var mySegmentsStorage: MySegmentsStorage? var myLargeSegmentsStorage: MySegmentsStorage? @@ -95,14 +95,17 @@ class InternalSplitClientStub: InternalSplitClient, @unchecked Sendable { return ["": SplitResult(treatment: SplitConstants.control)] } - func on(event: SplitEvent, queue: DispatchQueue, execute action: @escaping SplitAction) { - } + func on(event: SplitEvent, queue: DispatchQueue, execute action: @escaping SplitAction) {} - func on(event: SplitEvent, runInBackground: Bool, execute action: @escaping SplitAction) { - } + func on(event: SplitEvent, runInBackground: Bool, execute action: @escaping SplitAction) {} - func on(event: SplitEvent, execute action: @escaping SplitAction) { - } + func on(event: SplitEvent, execute action: @escaping SplitAction) {} + + func onSdkReady(action: @escaping (SdkReadyMetadata) -> Void) {} + + func onSdkReadyFromCache(action: @escaping (SdkReadyFromCacheMetadata) -> Void) {} + + func onSdkUpdate(action: @escaping (SdkUpdateMetadata) -> Void) {} func track(trafficType: String, eventType: String) -> Bool { return true diff --git a/SplitTests/Fake/SplitClientStub.swift b/SplitTests/Fake/SplitClientStub.swift index b3568b9d9..ea3573593 100644 --- a/SplitTests/Fake/SplitClientStub.swift +++ b/SplitTests/Fake/SplitClientStub.swift @@ -94,6 +94,12 @@ class SplitClientStub: SplitClient, @unchecked Sendable { func on(event: SplitEvent, runInBackground: Bool, queue: DispatchQueue?, execute action: @escaping SplitAction) { } + + func onSdkReady(action: @escaping (SdkReadyMetadata) -> Void) {} + + func onSdkReadyFromCache(action: @escaping (SdkReadyFromCacheMetadata) -> Void) {} + + func onSdkUpdate(action: @escaping (SdkUpdateMetadata) -> Void) {} func track(trafficType: String, eventType: String) -> Bool { return true From dcc6599fae215fc9b49dc80be907510061d3086c Mon Sep 17 00:00:00 2001 From: Martin Cardozo Date: Fri, 16 Jan 2026 13:02:47 -0300 Subject: [PATCH 4/7] New EventsListener --- Split/Api/DefaultSplitClient.swift | 28 ++++++++-------- Split/Api/FailHelpers.swift | 10 +++--- Split/Api/LocalhostSplitClient.swift | 33 ++++++++++++++----- Split/Api/SplitClient.swift | 18 ++++++---- SplitTests/Fake/InternalSplitClientStub.swift | 7 ++-- SplitTests/Fake/SplitClientStub.swift | 11 +++---- 6 files changed, 61 insertions(+), 46 deletions(-) diff --git a/Split/Api/DefaultSplitClient.swift b/Split/Api/DefaultSplitClient.swift index 64914f760..b99964058 100644 --- a/Split/Api/DefaultSplitClient.swift +++ b/Split/Api/DefaultSplitClient.swift @@ -6,7 +6,7 @@ import Foundation typealias DestroyHandler = () -> Void public final class DefaultSplitClient: NSObject, SplitClient, TelemetrySplitClient, @unchecked Sendable { - + private var storageContainer: SplitStorageContainer private var key: Key private let config: SplitClientConfig @@ -17,6 +17,7 @@ public final class DefaultSplitClient: NSObject, SplitClient, TelemetrySplitClie private var isClientDestroyed = false private let eventsTracker: EventsTracker private weak var clientManager: SplitClientManager? + @objc public var listener: SplitClientEventListener? var initStopwatch: Stopwatch? @@ -89,19 +90,18 @@ extension DefaultSplitClient { } // MARK: Events Listeners with Medatadata - @objc(onSdkReady:) - public func onSdkReady(action: @escaping (SdkReadyMetadata) -> Void) { - registerEvent(.sdkReady, action: action) - } - - @objc(onSdkReadyFromCache:) - public func onSdkReadyFromCache(action: @escaping (SdkReadyFromCacheMetadata) -> Void) { - registerEvent(.sdkReadyFromCache, action: action) - } - - @objc(onSdkUpdate:) - public func onSdkUpdate(action: @escaping (SdkUpdateMetadata) -> Void) { - registerEvent(.sdkUpdated, action: action) + @objc public func addEventsListener(_ listener: SplitClientEventListener) { + if let l = listener.onSdkReady { + registerEvent(.sdkReady, action: l) + } + + if let l = listener.onSdkReadyFromCache { + registerEvent(.sdkReadyFromCache, action: l) + } + + if let l = listener.onSdkUpdate { + registerEvent(.sdkUpdated, action: l) + } } private func registerEvent(_ event: SplitEvent, action: @escaping (T) -> Void) { diff --git a/Split/Api/FailHelpers.swift b/Split/Api/FailHelpers.swift index 76ec664c2..aa57f5335 100644 --- a/Split/Api/FailHelpers.swift +++ b/Split/Api/FailHelpers.swift @@ -60,13 +60,11 @@ class FailedClient: SplitClient { func on(event: SplitEvent, queue: DispatchQueue, execute action: @escaping SplitAction) {} - // MARK: Events with Metadata - func onSdkReady(action: @escaping (SdkReadyMetadata) -> Void) {} - - func onSdkReadyFromCache(action: @escaping (SdkReadyFromCacheMetadata) -> Void) {} - - func onSdkUpdate(action: @escaping (SdkUpdateMetadata) -> Void) {} + // MARK: Events Listeners with Medatadata + var listener: (any SplitClientEventListener)? + @objc public func addEventsListener(_ listener: SplitClientEventListener) {} + // MARK: Track func track(trafficType: String, eventType: String) -> Bool { false } diff --git a/Split/Api/LocalhostSplitClient.swift b/Split/Api/LocalhostSplitClient.swift index ee3b973a3..50423203a 100644 --- a/Split/Api/LocalhostSplitClient.swift +++ b/Split/Api/LocalhostSplitClient.swift @@ -41,20 +41,21 @@ import Foundation /// public final class LocalhostSplitClient: NSObject, SplitClient { - + private let splitsStorage: SplitsStorage private let mySegmentsStorage = EmptyMySegmentsStorage() private let eventsManager: SplitEventsManager? private var evaluator: Evaluator private let key: Key - weak var clientManger: SplitClientManager? + weak var clientManager: SplitClientManager? + @objc public var listener: SplitClientEventListener? init(key: Key, splitsStorage: SplitsStorage, clientManager: SplitClientManager?, eventsManager: SplitEventsManager? = nil, evaluator: Evaluator) { self.eventsManager = eventsManager self.key = key self.splitsStorage = splitsStorage - self.clientManger = clientManager + self.clientManager = clientManager self.evaluator = evaluator super.init() @@ -132,7 +133,7 @@ public final class LocalhostSplitClient: NSObject, SplitClient { private func on(event: SplitEvent, runInBackground: Bool, queue: DispatchQueue?, execute action: @escaping SplitAction) { - guard let factory = clientManger?.splitFactory else { return } + guard let factory = clientManager?.splitFactory else { return } if let eventsManager = self.eventsManager { let task = SplitEventActionTask(action: action, event: event, runInBackground: runInBackground, @@ -142,12 +143,26 @@ public final class LocalhostSplitClient: NSObject, SplitClient { } } - // MARK: Events with Metadata - public func onSdkReady(action: @escaping (SdkReadyMetadata) -> Void) {} - - public func onSdkReadyFromCache(action: @escaping (SdkReadyFromCacheMetadata) -> Void) {} + // MARK: Events Listeners with Medatadata + @objc public func addEventsListener(_ listener: SplitClientEventListener) { + if let l = listener.onSdkReady { + registerEvent(.sdkReady, action: l) + } + + if let l = listener.onSdkReadyFromCache { + registerEvent(.sdkReadyFromCache, action: l) + } + + if let l = listener.onSdkUpdate { + registerEvent(.sdkUpdated, action: l) + } + } - public func onSdkUpdate(action: @escaping (SdkUpdateMetadata) -> Void) {} + private func registerEvent(_ event: SplitEvent, action: @escaping (T) -> Void) { + guard let factory = clientManager?.splitFactory else { return } + let task = SplitEventActionTask(action: action, event: event, runInBackground: true, factory: factory, queue: nil) + eventsManager?.register(event: event, task: task) + } // MARK: Track public func track(trafficType: String, eventType: String) -> Bool { diff --git a/Split/Api/SplitClient.swift b/Split/Api/SplitClient.swift index c4ad66fdb..ac0451e22 100644 --- a/Split/Api/SplitClient.swift +++ b/Split/Api/SplitClient.swift @@ -11,6 +11,15 @@ import Foundation public typealias SplitAction = () -> Void public typealias SplitActionWithMetadata = (T) -> Void +@objc public protocol SplitClientEventListener: AnyObject { + @objc(onSdkReady:) + optional func onSdkReady(_ metadata: SdkReadyMetadata) + @objc(onSdkReadyFromCache:) + optional func onSdkReadyFromCache(_ metadata: SdkReadyFromCacheMetadata) + @objc(onSdkUpdate:) + optional func onSdkUpdate(_ metadata: SdkUpdateMetadata) +} + @objc public protocol SplitClient { // MARK: Evaluation feature @@ -39,12 +48,9 @@ public typealias SplitActionWithMetadata = (T) -> Void func on(event: SplitEvent, queue: DispatchQueue, execute action: @escaping SplitAction) // MARK: Events with Metadata - @objc(onSdkReady:) - func onSdkReady(action: @escaping (SdkReadyMetadata) -> Void) - @objc(onSdkReadyFromCache:) - func onSdkReadyFromCache(action: @escaping (SdkReadyFromCacheMetadata) -> Void) - @objc(onSdkUpdate:) - func onSdkUpdate(action: @escaping (SdkUpdateMetadata) -> Void) + @objc var listener: SplitClientEventListener? { get set } + @objc(addEventsListener:) + func addEventsListener(_ listener: SplitClientEventListener) // MARK: Track feature func track(trafficType: String, eventType: String) -> Bool diff --git a/SplitTests/Fake/InternalSplitClientStub.swift b/SplitTests/Fake/InternalSplitClientStub.swift index 08c4c5cbb..3ca5c4b34 100644 --- a/SplitTests/Fake/InternalSplitClientStub.swift +++ b/SplitTests/Fake/InternalSplitClientStub.swift @@ -14,6 +14,7 @@ class InternalSplitClientStub: InternalSplitClient, @unchecked Sendable { var splitsStorage: SplitsStorage? var mySegmentsStorage: MySegmentsStorage? var myLargeSegmentsStorage: MySegmentsStorage? + var listener: SplitClientEventListener? init(splitsStorage: SplitsStorage?, mySegmentsStorage: MySegmentsStorage?, @@ -101,11 +102,7 @@ class InternalSplitClientStub: InternalSplitClient, @unchecked Sendable { func on(event: SplitEvent, execute action: @escaping SplitAction) {} - func onSdkReady(action: @escaping (SdkReadyMetadata) -> Void) {} - - func onSdkReadyFromCache(action: @escaping (SdkReadyFromCacheMetadata) -> Void) {} - - func onSdkUpdate(action: @escaping (SdkUpdateMetadata) -> Void) {} + func addEventsListener(_ listener: SplitClientEventListener) {} func track(trafficType: String, eventType: String) -> Bool { return true diff --git a/SplitTests/Fake/SplitClientStub.swift b/SplitTests/Fake/SplitClientStub.swift index ea3573593..5ca6b1c26 100644 --- a/SplitTests/Fake/SplitClientStub.swift +++ b/SplitTests/Fake/SplitClientStub.swift @@ -11,6 +11,8 @@ import Foundation class SplitClientStub: SplitClient, @unchecked Sendable { + @objc public var listener: SplitClientEventListener? + func getTreatment(_ split: String, attributes: [String : Any]?) -> String { return SplitConstants.control } @@ -94,12 +96,9 @@ class SplitClientStub: SplitClient, @unchecked Sendable { func on(event: SplitEvent, runInBackground: Bool, queue: DispatchQueue?, execute action: @escaping SplitAction) { } - - func onSdkReady(action: @escaping (SdkReadyMetadata) -> Void) {} - - func onSdkReadyFromCache(action: @escaping (SdkReadyFromCacheMetadata) -> Void) {} - - func onSdkUpdate(action: @escaping (SdkUpdateMetadata) -> Void) {} + + func addEventsListener(_ listener: SplitClientEventListener) { + } func track(trafficType: String, eventType: String) -> Bool { return true From 7b9a999b7a2b516678645a67636355e142140c30 Mon Sep 17 00:00:00 2001 From: Martin Cardozo Date: Fri, 16 Jan 2026 13:06:17 -0300 Subject: [PATCH 5/7] Error message added --- Split/Events/SplitEventActionTask.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Split/Events/SplitEventActionTask.swift b/Split/Events/SplitEventActionTask.swift index 4d64ed522..54a56044e 100644 --- a/Split/Events/SplitEventActionTask.swift +++ b/Split/Events/SplitEventActionTask.swift @@ -13,7 +13,10 @@ class SplitEventActionTask: SplitEventTask, @unchecked Sendable { init(action: @escaping SplitActionWithMetadata, event: SplitEvent, runInBackground: Bool = false, factory: SplitFactory, queue: DispatchQueue? = nil) { self.eventHandlerWithMetadata = { metadata in - guard let typed = metadata as? T else { return } + guard let typed = metadata as? T else { + Logger.e("Wrong metadata type for this event (\(event.toString())).") + return + } action(typed) } self.event = event From 2d250ef6b2c3f6db913779ed2ddad138a22d987e Mon Sep 17 00:00:00 2001 From: Martin Cardozo Date: Fri, 16 Jan 2026 13:09:38 -0300 Subject: [PATCH 6/7] Comment improved. --- Split/Events/SplitEventActionTask.swift | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Split/Events/SplitEventActionTask.swift b/Split/Events/SplitEventActionTask.swift index 54a56044e..e29d002ab 100644 --- a/Split/Events/SplitEventActionTask.swift +++ b/Split/Events/SplitEventActionTask.swift @@ -12,6 +12,13 @@ class SplitEventActionTask: SplitEventTask, @unchecked Sendable { var factory: SplitFactory init(action: @escaping SplitActionWithMetadata, event: SplitEvent, runInBackground: Bool = false, factory: SplitFactory, queue: DispatchQueue? = nil) { + + self.event = event + self.runInBackground = runInBackground + self.queue = queue + self.factory = factory + + // Metadata: "swap" for concrete type and ensure type is correct for this event self.eventHandlerWithMetadata = { metadata in guard let typed = metadata as? T else { Logger.e("Wrong metadata type for this event (\(event.toString())).") @@ -19,10 +26,6 @@ class SplitEventActionTask: SplitEventTask, @unchecked Sendable { } action(typed) } - self.event = event - self.runInBackground = runInBackground - self.queue = queue - self.factory = factory } init(action: @escaping SplitAction, event: SplitEvent, runInBackground: Bool = false, factory: SplitFactory, queue: DispatchQueue? = nil) { From 9f5d294db0c3d91b512c3deb9d9a15253dffc73e Mon Sep 17 00:00:00 2001 From: Martin Cardozo Date: Fri, 16 Jan 2026 14:51:12 -0300 Subject: [PATCH 7/7] Unnamed parameters removed. --- Split/Api/DefaultSplitClient.swift | 2 +- Split/Api/FailHelpers.swift | 2 +- Split/Api/LocalhostSplitClient.swift | 2 +- Split/Api/SplitClient.swift | 2 +- SplitTests/Fake/InternalSplitClientStub.swift | 2 +- SplitTests/Fake/SplitClientStub.swift | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Split/Api/DefaultSplitClient.swift b/Split/Api/DefaultSplitClient.swift index b99964058..351a462b2 100644 --- a/Split/Api/DefaultSplitClient.swift +++ b/Split/Api/DefaultSplitClient.swift @@ -90,7 +90,7 @@ extension DefaultSplitClient { } // MARK: Events Listeners with Medatadata - @objc public func addEventsListener(_ listener: SplitClientEventListener) { + @objc public func addEventsListener(listener: SplitClientEventListener) { if let l = listener.onSdkReady { registerEvent(.sdkReady, action: l) } diff --git a/Split/Api/FailHelpers.swift b/Split/Api/FailHelpers.swift index aa57f5335..2075fd786 100644 --- a/Split/Api/FailHelpers.swift +++ b/Split/Api/FailHelpers.swift @@ -62,7 +62,7 @@ class FailedClient: SplitClient { // MARK: Events Listeners with Medatadata var listener: (any SplitClientEventListener)? - @objc public func addEventsListener(_ listener: SplitClientEventListener) {} + @objc public func addEventsListener(listener: SplitClientEventListener) {} // MARK: Track func track(trafficType: String, eventType: String) -> Bool { diff --git a/Split/Api/LocalhostSplitClient.swift b/Split/Api/LocalhostSplitClient.swift index 50423203a..18920d36d 100644 --- a/Split/Api/LocalhostSplitClient.swift +++ b/Split/Api/LocalhostSplitClient.swift @@ -144,7 +144,7 @@ public final class LocalhostSplitClient: NSObject, SplitClient { } // MARK: Events Listeners with Medatadata - @objc public func addEventsListener(_ listener: SplitClientEventListener) { + @objc public func addEventsListener(listener: SplitClientEventListener) { if let l = listener.onSdkReady { registerEvent(.sdkReady, action: l) } diff --git a/Split/Api/SplitClient.swift b/Split/Api/SplitClient.swift index ac0451e22..bc330d292 100644 --- a/Split/Api/SplitClient.swift +++ b/Split/Api/SplitClient.swift @@ -50,7 +50,7 @@ public typealias SplitActionWithMetadata = (T) -> Void // MARK: Events with Metadata @objc var listener: SplitClientEventListener? { get set } @objc(addEventsListener:) - func addEventsListener(_ listener: SplitClientEventListener) + func addEventsListener(listener: SplitClientEventListener) // MARK: Track feature func track(trafficType: String, eventType: String) -> Bool diff --git a/SplitTests/Fake/InternalSplitClientStub.swift b/SplitTests/Fake/InternalSplitClientStub.swift index 3ca5c4b34..ada32efd6 100644 --- a/SplitTests/Fake/InternalSplitClientStub.swift +++ b/SplitTests/Fake/InternalSplitClientStub.swift @@ -102,7 +102,7 @@ class InternalSplitClientStub: InternalSplitClient, @unchecked Sendable { func on(event: SplitEvent, execute action: @escaping SplitAction) {} - func addEventsListener(_ listener: SplitClientEventListener) {} + func addEventsListener(listener: SplitClientEventListener) {} func track(trafficType: String, eventType: String) -> Bool { return true diff --git a/SplitTests/Fake/SplitClientStub.swift b/SplitTests/Fake/SplitClientStub.swift index 5ca6b1c26..697c061a4 100644 --- a/SplitTests/Fake/SplitClientStub.swift +++ b/SplitTests/Fake/SplitClientStub.swift @@ -97,7 +97,7 @@ class SplitClientStub: SplitClient, @unchecked Sendable { func on(event: SplitEvent, runInBackground: Bool, queue: DispatchQueue?, execute action: @escaping SplitAction) { } - func addEventsListener(_ listener: SplitClientEventListener) { + func addEventsListener(listener: SplitClientEventListener) { } func track(trafficType: String, eventType: String) -> Bool {