Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Split.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,8 @@
5B7E60142F0D67C9003B32B9 /* SplitFlakyTests.xctestplan in Resources */ = {isa = PBXBuildFile; fileRef = 5B7E60132F0D67C9003B32B9 /* SplitFlakyTests.xctestplan */; };
5B7E60152F0D67C9003B32B9 /* SplitFlakyTests.xctestplan in Resources */ = {isa = PBXBuildFile; fileRef = 5B7E60132F0D67C9003B32B9 /* SplitFlakyTests.xctestplan */; };
5B91B8392DDE4A3B000510F0 /* SplitDTOTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B91B8382DDE4A30000510F0 /* SplitDTOTests.swift */; };
5BAB399E2F17EEB000843533 /* SplitMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BAB399D2F17EEAA00843533 /* SplitMetadata.swift */; };
5BAB399F2F17EEB000843533 /* SplitMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BAB399D2F17EEAA00843533 /* SplitMetadata.swift */; };
5BD75F832E5C9B5700F9EFBD /* SplitiOSUnit_5.xctestplan in Resources */ = {isa = PBXBuildFile; fileRef = 5BD75F822E5C9B5700F9EFBD /* SplitiOSUnit_5.xctestplan */; };
5BD75FB02E5DF0DB00F9EFBD /* FallbackTreatments.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD75FAF2E5DF0D700F9EFBD /* FallbackTreatments.swift */; };
5BD75FB12E5DF0DB00F9EFBD /* FallbackTreatments.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD75FAF2E5DF0D700F9EFBD /* FallbackTreatments.swift */; };
Expand Down Expand Up @@ -2060,6 +2062,7 @@
5B3C18052ED76BAE0068D623 /* SplitTests copy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "SplitTests copy-Info.plist"; path = "/Users/martin/Desktop/Code/ios-client/SplitTests copy-Info.plist"; sourceTree = "<absolute>"; };
5B7E60132F0D67C9003B32B9 /* SplitFlakyTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = SplitFlakyTests.xctestplan; sourceTree = "<group>"; };
5B91B8382DDE4A30000510F0 /* SplitDTOTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplitDTOTests.swift; sourceTree = "<group>"; };
5BAB399D2F17EEAA00843533 /* SplitMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplitMetadata.swift; sourceTree = "<group>"; };
5BD75F822E5C9B5700F9EFBD /* SplitiOSUnit_5.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = SplitiOSUnit_5.xctestplan; sourceTree = "<group>"; };
5BD75FAF2E5DF0D700F9EFBD /* FallbackTreatments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FallbackTreatments.swift; sourceTree = "<group>"; };
5BD75FB22E5DF15700F9EFBD /* FallbackSanitizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FallbackSanitizer.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2938,6 +2941,7 @@
3B6DEEBE20EA6AE20067435E /* Events */ = {
isa = PBXGroup;
children = (
5BAB399D2F17EEAA00843533 /* SplitMetadata.swift */,
3B6DEEC420EA6AE20067435E /* SplitEvent.swift */,
3B6DEEC520EA6AE20067435E /* SplitEventsManager.swift */,
9530FD7927F24306005027AA /* EventsManagerCoordinator.swift */,
Expand Down Expand Up @@ -4958,6 +4962,7 @@
3B6DEF4F20EA6AE50067435E /* TrafficType.swift in Sources */,
3B6DEF8020EA6AE50067435E /* RestClient.swift in Sources */,
C5A3F5212BEBDAD6009FACD3 /* HttpParameter.swift in Sources */,
5BAB399F2F17EEB000843533 /* SplitMetadata.swift in Sources */,
9505681C26822E96001D7B10 /* ImpressionsCounter.swift in Sources */,
950B743426938B5E005FD649 /* KeyImpression.swift in Sources */,
3B6DEF7020EA6AE50067435E /* Whitelist.swift in Sources */,
Expand Down Expand Up @@ -6159,6 +6164,7 @@
95B02D8228D0BDC30030EC8B /* Json.swift in Sources */,
95B02D8328D0BDC30030EC8B /* GenericError.swift in Sources */,
95B02D8428D0BDC30030EC8B /* HttpRequest.swift in Sources */,
5BAB399E2F17EEB000843533 /* SplitMetadata.swift in Sources */,
95B02D8528D0BDC30030EC8B /* HttpDataResponse.swift in Sources */,
95B02D8628D0BDC30030EC8B /* HttpResponse.swift in Sources */,
95B02D8728D0BDC30030EC8B /* HttpClient.swift in Sources */,
Expand Down
10 changes: 10 additions & 0 deletions Split/Events/SplitInternalEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,13 @@ enum SplitInternalEvent {
case sdkReadyTimeoutReached
case splitKilledNotification
}

struct SplitInternalEventWithMetadata {
let type: SplitInternalEvent
let metadata: EventMetadata?

init(_ type: SplitInternalEvent, metadata: EventMetadata? = nil) {
self.type = type
self.metadata = metadata
}
}
90 changes: 90 additions & 0 deletions Split/Events/SplitMetadata.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Created by Martin Cardozo on 13/01/2026

import Foundation

protocol EventMetadata {}

// MARK: UPDATE
/// Represents the type of SDK update that triggered a metadata callback.
///
/// This enum is used inside `SdkUpdateMetadata` to indicate **what kind of data
/// was updated internally by the SDK**.
///
/// - flagsUpdate:
/// One or more feature flags were updated.
/// - segmentsUpdate:
/// One or more user segments were updated.
///
@objc public enum SdkUpdateMetadataType: Int {
case FLAGS_UPDATE
case SEGMENTS_UPDATE
}

/// Metadata for SDK update event.
///
/// This object is delivered to update callbacks to provide
/// contextual information about **what changed inside the SDK**.
///
/// It includes:
/// - The type of update that occurred (flags or segments)
/// - The specific flags affected
///
@objc public class SdkUpdateMetadata: NSObject, EventMetadata {

@objc public private(set) var type: SdkUpdateMetadataType

/// The names of the entities affected by the update.
@objc public private(set) var names: [String] = []

@available(*, unavailable)
override init() {
fatalError("Use SDK-provided instances only")
}
}

// MARK: READY
/// Metadata for SDK ready event.
///
/// This object is delivered when the SDK reaches a ready state,
/// providing information about **how and when the data was loaded**.
///
/// It includes:
/// - The timestamp of the last successful update.
/// - Whether the data was loaded from the initial cache.
///
@objc public class SdkReadyMetadata: NSObject, EventMetadata {

/// Timestamp (in milliseconds since epoch) of the last successful SDK update.
///
/// A value of `-1` indicates that no update has occurred yet.
@objc public private(set) var lastUpdateTimestamp: Int64 = -1

/// Indicates whether this SDK initialization corresponds to a fresh install.
@objc public private(set) var isInitialCacheLoad: Bool = false

@available(*, unavailable)
override init() {
fatalError("Use SDK-provided instances only")
}
}

// MARK: READY FROM CACHE
/// Metadata for SDK ready-from-cache event.
///
/// This object is delivered when the SDK becomes ready **using cached data**
/// before any successful network update has occurred.
///
/// It indicates that:
/// - The SDK initialized using previously stored data.
/// - No fresh data has been fetched from the network yet.
///
@objc public class SdkReadyFromCacheMetadata: NSObject, EventMetadata {

/// Indicates whether this SDK initialization corresponds to a fresh install.
@objc public private(set) var isInitialCacheLoad: Bool = false

@available(*, unavailable)
override init() {
fatalError("Use SDK-provided instances only")
}
}
Loading