Skip to content

Performed fixup for url options, lifecycle updates, objc compatibility #396

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jul 14, 2025
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
5 changes: 0 additions & 5 deletions .github/workflows/swift.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,6 @@ jobs:
needs: cancel_previous
runs-on: macos-15
steps:
- name: Install yeetd
run: |
wget https://github.com/biscuitehh/yeetd/releases/download/1.0/yeetd-normal.pkg
sudo installer -pkg yeetd-normal.pkg -target /
yeetd &
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: "16.2"
Expand Down
2 changes: 1 addition & 1 deletion Examples/apps/BasicExample/BasicExample/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// Override point for customization after application launch.

let configuration = Configuration(writeKey: "WRITE KEY")
.trackApplicationLifecycleEvents(true)
.setTrackedApplicationLifecycleEvents(.all)
.flushInterval(10)
.flushAt(2)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// Override point for customization after application launch.

let configuration = Configuration(writeKey: "EioRQCqLHUECnoSseEguI8GnxOlZTOyX")
.trackApplicationLifecycleEvents(true)
.setTrackedApplicationLifecycleEvents(.all)
.flushInterval(1)

analytics = Analytics(configuration: configuration)
Expand Down
2 changes: 1 addition & 1 deletion Examples/apps/MacExample/MacExample/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
// Insert code here to initialize your application

let configuration = Configuration(writeKey: "<WRITE KEY>")
.trackApplicationLifecycleEvents(true)
.setTrackedApplicationLifecycleEvents(.all)
.flushInterval(10)
.flushAt(1)
.errorHandler { error in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,5 +101,5 @@ extension Analytics {
static var main = Analytics(configuration:
Configuration(writeKey: "ABCD")
.flushAt(3)
.trackApplicationLifecycleEvents(true))
.setTrackedApplicationLifecycleEvents(.all))
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ extension Analytics {
static var main = Analytics(configuration:
Configuration(writeKey: "ABCD")
.flushAt(3)
.trackApplicationLifecycleEvents(true))
.setTrackedApplicationLifecycleEvents(.all))
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class ExtensionDelegate: NSObject, WKExtensionDelegate {
func applicationDidFinishLaunching() {
// Perform any final initialization of your application.
let configuration = Configuration(writeKey: "WRITE KEY")
.trackApplicationLifecycleEvents(true)
.setTrackedApplicationLifecycleEvents(.all)
.flushInterval(10)

analytics = Analytics(configuration: configuration)
Expand Down
6 changes: 3 additions & 3 deletions Examples/tasks/MultiInstance.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ import Segment
extension Analytics {
static var main = Analytics(configuration: Configuration(writeKey: "1234")
.flushAt(3)
.trackApplicationLifecycleEvents(true))
.setTrackedApplicationLifecycleEvents(.all))

static var support = Analytics(configuration: Configuration(writeKey: "5678")
.flushAt(10)
.trackApplicationLifecycleEvents(false))
.setTrackedApplicationLifecycleEvents(.none))
}
72 changes: 70 additions & 2 deletions Sources/Segment/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,68 @@

// MARK: - Internal Configuration

@objc(SEGTrackedLifecycleEvent)
public final class TrackedLifecycleEvent: NSObject, OptionSet {
public let rawValue: Int

public init(rawValue: Int) {
self.rawValue = rawValue
}

public override func isEqual(_ object: Any?) -> Bool {
(object as? Self)?.rawValue == rawValue
}

public override var hash: Int {
rawValue.hashValue
}

Check warning on line 64 in Sources/Segment/Configuration.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Segment/Configuration.swift#L62-L64

Added lines #L62 - L64 were not covered by tests

@objc public static let none: TrackedLifecycleEvent = []
@objc public static let applicationInstalled = TrackedLifecycleEvent(rawValue: 1 << 0)
@objc public static let applicationUpdated = TrackedLifecycleEvent(rawValue: 1 << 1)
@objc public static let applicationOpened = TrackedLifecycleEvent(rawValue: 1 << 2)
@objc public static let applicationBackgrounded = TrackedLifecycleEvent(rawValue: 1 << 3)
@objc public static let applicationForegrounded = TrackedLifecycleEvent(rawValue: 1 << 4)
#if os(macOS)
@objc public static let applicationUnhidden = TrackedLifecycleEvent(rawValue: 1 << 5)
@objc public static let applicationHidden = TrackedLifecycleEvent(rawValue: 1 << 6)
@objc public static let applicationTerminated = TrackedLifecycleEvent(rawValue: 1 << 7)

@objc public static let all: TrackedLifecycleEvent = [
.applicationInstalled,
.applicationUpdated,
.applicationOpened,
.applicationBackgrounded,
.applicationForegrounded,
.applicationUnhidden,
.applicationHidden,
.applicationTerminated,
]
#elseif os(iOS) || os(tvOS) || os(visionOS) || targetEnvironment(macCatalyst)
@objc public static let all: TrackedLifecycleEvent = [
.applicationInstalled,
.applicationUpdated,
.applicationOpened,
.applicationBackgrounded,
.applicationForegrounded,
]
#elseif os(watchOS)
@objc public static let all: TrackedLifecycleEvent = [
.applicationInstalled,
.applicationUpdated,
.applicationOpened,
.applicationBackgrounded,
]
#else
@objc public static let all = TrackedLifecycleEvent.none
#endif
}

public class Configuration {
internal struct Values {
var writeKey: String
var application: Any? = nil
var trackApplicationLifecycleEvents: Bool = true
var trackedApplicationLifecycleEvents = TrackedLifecycleEvent.all
var flushAt: Int = 20
var flushInterval: TimeInterval = 30
var defaultSettings: Settings? = nil
Expand Down Expand Up @@ -110,8 +167,19 @@
/// - Parameter enabled: A bool value
/// - Returns: The current Configuration.
@discardableResult
@available(*, deprecated, message: "Use `setTrackedApplicationLifecycleEvents(_:)` for more granular control")
func trackApplicationLifecycleEvents(_ enabled: Bool) -> Configuration {
values.trackApplicationLifecycleEvents = enabled
values.trackedApplicationLifecycleEvents = enabled ? .all : .none
return self
}

/// Opt-in/out of tracking lifecycle events. The default value is `.none`.
///
/// - Parameter events: An option set of the events to track.
/// - Returns: The current Configuration.
@discardableResult
func setTrackedApplicationLifecycleEvents(_ events: TrackedLifecycleEvent) -> Configuration {
values.trackedApplicationLifecycleEvents = events

Check warning on line 182 in Sources/Segment/Configuration.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Segment/Configuration.swift#L181-L182

Added lines #L181 - L182 were not covered by tests
return self
}

Expand Down
7 changes: 4 additions & 3 deletions Sources/Segment/ObjC/ObjCConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,21 @@
}
}

/// Opt-in/out of tracking lifecycle events. The default value is `false`.
/// Opt-in/out of tracking lifecycle events. The default value is `true`.
/// NOTE: the default differs from analytics-ios.
@objc
public var trackApplicationLifecycleEvents: Bool {
get {
return configuration.values.trackApplicationLifecycleEvents
return (configuration.values.trackedApplicationLifecycleEvents != .none)

Check warning on line 35 in Sources/Segment/ObjC/ObjCConfiguration.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Segment/ObjC/ObjCConfiguration.swift#L35

Added line #L35 was not covered by tests
}
set(value) {
configuration.trackApplicationLifecycleEvents(value)
configuration.setTrackedApplicationLifecycleEvents(.all)
}
}

/// Set the number of events necessary to automatically flush. The default
/// value is `20`.
@objc

Check warning on line 44 in Sources/Segment/ObjC/ObjCConfiguration.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Segment/ObjC/ObjCConfiguration.swift#L38-L44

Added lines #L38 - L44 were not covered by tests
public var flushAt: Int {
get {
return configuration.values.flushAt
Expand Down
79 changes: 36 additions & 43 deletions Sources/Segment/Plugins/Platforms/Mac/macOSLifecycleEvents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@
// Make sure we aren't double calling application:didFinishLaunchingWithOptions
// by resetting the check at the start
_didFinishLaunching.set(true)

if analytics?.configuration.values.trackApplicationLifecycleEvents == false {
return
}

let previousVersion = UserDefaults.standard.string(forKey: Self.versionKey)
let previousBuild = UserDefaults.standard.string(forKey: Self.buildKey)
Expand All @@ -40,64 +36,63 @@
let currentBuild = Bundle.main.infoDictionary?["CFBundleVersion"] as? String

if previousBuild == nil {
analytics?.track(name: "Application Installed", properties: [
"version": currentVersion ?? "",
"build": currentBuild ?? ""
])
if analytics?.configuration.values.trackedApplicationLifecycleEvents.contains(.applicationInstalled) == true {
analytics?.track(name: "Application Installed", properties: [
"version": currentVersion ?? "",
"build": currentBuild ?? ""
])
}
} else if currentBuild != previousBuild {
analytics?.track(name: "Application Updated", properties: [
"previous_version": previousVersion ?? "",
"previous_build": previousBuild ?? "",
if analytics?.configuration.values.trackedApplicationLifecycleEvents.contains(.applicationUpdated) == true {
analytics?.track(name: "Application Updated", properties: [
"previous_version": previousVersion ?? "",
"previous_build": previousBuild ?? "",
"version": currentVersion ?? "",
"build": currentBuild ?? ""
])
}
}

if analytics?.configuration.values.trackedApplicationLifecycleEvents.contains(.applicationOpened) == true {
analytics?.track(name: "Application Opened", properties: [
"from_background": false,

Check warning on line 58 in Sources/Segment/Plugins/Platforms/Mac/macOSLifecycleEvents.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Segment/Plugins/Platforms/Mac/macOSLifecycleEvents.swift#L46-L58

Added lines #L46 - L58 were not covered by tests
"version": currentVersion ?? "",
"build": currentBuild ?? ""
])
}

analytics?.track(name: "Application Opened", properties: [
"from_background": false,
"version": currentVersion ?? "",
"build": currentBuild ?? ""
])


Check warning on line 63 in Sources/Segment/Plugins/Platforms/Mac/macOSLifecycleEvents.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Segment/Plugins/Platforms/Mac/macOSLifecycleEvents.swift#L63

Added line #L63 was not covered by tests
UserDefaults.standard.setValue(currentVersion, forKey: Self.versionKey)
UserDefaults.standard.setValue(currentBuild, forKey: Self.buildKey)
}

func applicationDidUnhide() {
if analytics?.configuration.values.trackApplicationLifecycleEvents == false {
return
if analytics?.configuration.values.trackedApplicationLifecycleEvents.contains(.applicationUnhidden) == true {
let currentVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
let currentBuild = Bundle.main.infoDictionary?["CFBundleVersion"] as? String

analytics?.track(name: "Application Unhidden", properties: [
"from_background": true,
"version": currentVersion ?? "",
"build": currentBuild ?? ""
])

Check warning on line 77 in Sources/Segment/Plugins/Platforms/Mac/macOSLifecycleEvents.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Segment/Plugins/Platforms/Mac/macOSLifecycleEvents.swift#L69-L77

Added lines #L69 - L77 were not covered by tests
}

let currentVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
let currentBuild = Bundle.main.infoDictionary?["CFBundleVersion"] as? String

analytics?.track(name: "Application Unhidden", properties: [
"from_background": true,
"version": currentVersion ?? "",
"build": currentBuild ?? ""
])
}

func applicationDidHide() {
if analytics?.configuration.values.trackApplicationLifecycleEvents == false {
return
if analytics?.configuration.values.trackedApplicationLifecycleEvents.contains(.applicationHidden) == true {
analytics?.track(name: "Application Hidden")

Check warning on line 83 in Sources/Segment/Plugins/Platforms/Mac/macOSLifecycleEvents.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Segment/Plugins/Platforms/Mac/macOSLifecycleEvents.swift#L82-L83

Added lines #L82 - L83 were not covered by tests
}

analytics?.track(name: "Application Hidden")
}
func applicationDidResignActive() {
if analytics?.configuration.values.trackApplicationLifecycleEvents == false {
return
if analytics?.configuration.values.trackedApplicationLifecycleEvents.contains(.applicationBackgrounded) == true {
analytics?.track(name: "Application Backgrounded")

Check warning on line 88 in Sources/Segment/Plugins/Platforms/Mac/macOSLifecycleEvents.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Segment/Plugins/Platforms/Mac/macOSLifecycleEvents.swift#L87-L88

Added lines #L87 - L88 were not covered by tests
}

analytics?.track(name: "Application Backgrounded")
}

func applicationDidBecomeActive() {
if analytics?.configuration.values.trackApplicationLifecycleEvents == false {
if analytics?.configuration.values.trackedApplicationLifecycleEvents.contains(.applicationForegrounded) == false {

Check warning on line 93 in Sources/Segment/Plugins/Platforms/Mac/macOSLifecycleEvents.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Segment/Plugins/Platforms/Mac/macOSLifecycleEvents.swift#L93

Added line #L93 was not covered by tests
return
}

analytics?.track(name: "Application Foregrounded")

// Lets check if we skipped application:didFinishLaunchingWithOptions,
Expand All @@ -109,11 +104,9 @@
}

func applicationWillTerminate() {
if analytics?.configuration.values.trackApplicationLifecycleEvents == false {
return
if analytics?.configuration.values.trackedApplicationLifecycleEvents.contains(.applicationTerminated) == true {
analytics?.track(name: "Application Terminated")

Check warning on line 108 in Sources/Segment/Plugins/Platforms/Mac/macOSLifecycleEvents.swift

View check run for this annotation

Codecov / codecov/patch

Sources/Segment/Plugins/Platforms/Mac/macOSLifecycleEvents.swift#L107-L108

Added lines #L107 - L108 were not covered by tests
}

analytics?.track(name: "Application Terminated")
}
}

Expand Down
Loading