Skip to content

Instantly share code, notes, and snippets.

@astrokin
Last active January 31, 2024 19:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save astrokin/ffa8d9aa92a23a76150f414fffa249d6 to your computer and use it in GitHub Desktop.
Save astrokin/ffa8d9aa92a23a76150f414fffa249d6 to your computer and use it in GitHub Desktop.
extension AnalyticsEvent: TrackingEvent {
var trackingName: String {
MirroringHelper.name(from: self)
}
var trackingAttributes: [String: String] {
MirroringHelper.attributes(from: self)
}
}
public protocol TrackingEvent {
var trackingName: String { get }
var trackingAttributes: [String: String] { get }
}
public enum TrackingPolicy {
case multipleTracking
case trackOnce
}
public protocol AnalyticsService {
func track(event: TrackingEvent, trackingPolicy: TrackingPolicy)
func track(userProperties: [String: Any])
}
public enum MirroringHelper {
public static func reflection(on obj: Any) -> [String: String] {
let reflection = Mirror(reflecting: obj)
guard reflection.displayStyle == .enum,
let associated = reflection.children.first
else {
return [:]
}
let values = Mirror(reflecting: associated.value).children
var valuesArray = [String: String]()
for case let item in values where item.label != nil {
// swiftlint:disable:next force_unwrapping
valuesArray[item.label!] = String(describing: item.value)
}
let result = Dictionary(uniqueKeysWithValues: valuesArray.filter { $0.value != "nil" }.map { ($0.key, unwrapped($0.value)) })
return result
}
public static func name(from obj: Any) -> String {
let mirror = Mirror(reflecting: obj)
if let label = mirror.children.first?.label {
return label
} else {
return String(describing: obj)
}
}
public static func attributes(from obj: Any) -> [String: String] {
var result = MirroringHelper.reflection(on: obj)
let name = name(from: obj)
counted(name: name, attributes: &result)
return result
}
public static func counted(name: String, attributes: inout [String: String]) {
var count = Foundation.UserDefaults.standard.integer(forKey: name)
count += 1
Foundation.UserDefaults.standard.set(count, forKey: name)
attributes["count"] = "\(count)"
}
private static func unwrapped(_ value: String) -> String {
guard value.starts(with: "Optional(") else {
return value
}
return String(value.replacingOccurrences(of: "Optional(", with: "").dropLast().replacingOccurrences(of: "\"", with: ""))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment