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
54 changes: 53 additions & 1 deletion Sources/Segment/Analytics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,34 @@ public class Analytics {

public var timeline: Timeline

static internal let deadInstance = "DEADINSTANCE"
static internal weak var firstInstance: Analytics? = nil

/**
This method isn't a traditional singleton implementation. It's provided here
to ease migration from analytics-ios to analytics-swift. Rather than return a
singleton, it returns the first instance of Analytics created, OR an instance
who's writekey is "DEADINSTANCE".

In the case of a dead instance, an assert will be thrown when in DEBUG builds to
assist developers in knowning that `shared()` is being called too soon.
*/
static func shared() -> Analytics {
if let a = firstInstance {
if a.isDead == false {
return a
}
}

#if DEBUG
if isUnitTesting == false {
assert(true == false, "An instance of Analytice does not exist!")
}
#endif

return Analytics(configuration: Configuration(writeKey: deadInstance))
}

/// Initialize this instance of Analytics with a given configuration setup.
/// - Parameters:
/// - configuration: The configuration to use
Expand All @@ -40,6 +68,8 @@ public class Analytics {

storage.analytics = self

checkSharedInstance()

// Get everything running
platformStartup()
}
Expand Down Expand Up @@ -142,8 +172,8 @@ extension Analytics {
}
}

/// Returns a list of currently active flush policies.
public var flushPolicies: [FlushPolicy] {

get {
configuration.values.flushPolicies
}
Expand Down Expand Up @@ -332,3 +362,25 @@ extension Analytics {
track(name: "Deep Link Opened", properties: jsonProperties)
}
}

// MARK: Private Stuff

extension Analytics {
private func checkSharedInstance() {
// is firstInstance a dead one? If so, override it.
if let firstInstance = Self.firstInstance {
if firstInstance.isDead {
Self.firstInstance = self
}
}
// is firstInstance nil? If so, set it.
if Self.firstInstance == nil {
Self.firstInstance = self
}
}

/// Determines if an instance is dead.
internal var isDead: Bool {
return configuration.values.writeKey == Self.deadInstance
}
}
21 changes: 21 additions & 0 deletions Tests/Segment-Tests/Analytics_Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -620,4 +620,25 @@ final class Analytics_Tests: XCTestCase {
XCTAssertTrue(destHit)

}

func testSharedInstance() {
Analytics.firstInstance = nil

let dead = Analytics.shared()
XCTAssertTrue(dead.isDead)

let alive = Analytics(configuration: Configuration(writeKey: "1234"))
XCTAssertFalse(alive.isDead)

let shared = Analytics.shared()
XCTAssertFalse(shared.isDead)

XCTAssertTrue(alive === shared)

let alive2 = Analytics(configuration: Configuration(writeKey: "ABCD"))
let shared2 = Analytics.shared()
XCTAssertFalse(alive2 === shared2)
XCTAssertTrue(shared2 === shared)

}
}