mixpanel-swift/Sources/Mixpanel.swift
2021-09-06 22:44:41 -07:00

216 lines
7.9 KiB
Swift

//
// Mixpanel.swift
// Mixpanel
//
// Created by Yarden Eitan on 6/1/16.
// Copyright © 2016 Mixpanel. All rights reserved.
//
import Foundation
#if !os(OSX)
import UIKit
#endif // os(OSX)
/// The primary class for integrating Mixpanel with your app.
open class Mixpanel {
#if !os(OSX) && !os(watchOS)
/**
Initializes an instance of the API with the given project token.
Returns a new Mixpanel instance API object. This allows you to create more than one instance
of the API object, which is convenient if you'd like to send data to more than
one Mixpanel project from a single app.
- parameter token: your project token
- parameter flushInterval: Optional. Interval to run background flushing
- parameter instanceName: Optional. The name you want to call this instance
- parameter optOutTrackingByDefault: Optional. Whether or not to be opted out from tracking by default
- important: If you have more than one Mixpanel instance, it is beneficial to initialize
the instances with an instanceName. Then they can be reached by calling getInstance with name.
- returns: returns a mixpanel instance if needed to keep throughout the project.
You can always get the instance by calling getInstance(name)
*/
@discardableResult
open class func initialize(token apiToken: String,
flushInterval: Double = 60,
instanceName: String = UUID().uuidString,
optOutTrackingByDefault: Bool = false) -> MixpanelInstance {
return MixpanelManager.sharedInstance.initialize(token: apiToken,
flushInterval: flushInterval,
instanceName: instanceName,
optOutTrackingByDefault: optOutTrackingByDefault)
}
#else
/**
Initializes an instance of the API with the given project token (MAC OS ONLY).
Returns a new Mixpanel instance API object. This allows you to create more than one instance
of the API object, which is convenient if you'd like to send data to more than
one Mixpanel project from a single app.
- parameter token: your project token
- parameter flushInterval: Optional. Interval to run background flushing
- parameter instanceName: Optional. The name you want to call this instance
- parameter optOutTrackingByDefault: Optional. Whether or not to be opted out from tracking by default
- important: If you have more than one Mixpanel instance, it is beneficial to initialize
the instances with an instanceName. Then they can be reached by calling getInstance with name.
- returns: returns a mixpanel instance if needed to keep throughout the project.
You can always get the instance by calling getInstance(name)
*/
@discardableResult
open class func initialize(token apiToken: String,
flushInterval: Double = 60,
instanceName: String = UUID().uuidString,
optOutTrackingByDefault: Bool = false) -> MixpanelInstance {
return MixpanelManager.sharedInstance.initialize(token: apiToken,
flushInterval: flushInterval,
instanceName: instanceName,
optOutTrackingByDefault: optOutTrackingByDefault)
}
#endif // os(OSX)
/**
Gets the mixpanel instance with the given name
- parameter name: the instance name
- returns: returns the mixpanel instance
*/
open class func getInstance(name: String) -> MixpanelInstance? {
return MixpanelManager.sharedInstance.getInstance(name: name)
}
/**
Returns the main instance that was initialized.
If not specified explicitly, the main instance is always the last instance added
- returns: returns the main Mixpanel instance
*/
open class func mainInstance() -> MixpanelInstance {
if let instance = MixpanelManager.sharedInstance.getMainInstance() {
return instance
} else {
assert(false, "You have to call initialize(token:) before calling the main instance, " +
"or define a new main instance if removing the main one")
return Mixpanel.initialize(token: "")
}
}
/**
Sets the main instance based on the instance name
- parameter name: the instance name
*/
open class func setMainInstance(name: String) {
MixpanelManager.sharedInstance.setMainInstance(name: name)
}
/**
Removes an unneeded Mixpanel instance based on its name
- parameter name: the instance name
*/
open class func removeInstance(name: String) {
MixpanelManager.sharedInstance.removeInstance(name: name)
}
}
class MixpanelManager {
static let sharedInstance = MixpanelManager()
private var instances: [String: MixpanelInstance]
private var mainInstance: MixpanelInstance?
private let readWriteLock: ReadWriteLock
init() {
instances = [String: MixpanelInstance]()
Logger.addLogging(PrintLogging())
readWriteLock = ReadWriteLock(label: "com.mixpanel.instance.manager.lock")
}
#if !os(OSX) && !os(watchOS)
func initialize(token apiToken: String,
flushInterval: Double,
instanceName: String,
optOutTrackingByDefault: Bool = false) -> MixpanelInstance {
let instance = MixpanelInstance(apiToken: apiToken,
flushInterval: flushInterval,
name: instanceName,
optOutTrackingByDefault: optOutTrackingByDefault)
mainInstance = instance
readWriteLock.write {
instances[instanceName] = instance
}
return instance
}
#else
func initialize(token apiToken: String,
flushInterval: Double,
instanceName: String,
optOutTrackingByDefault: Bool = false) -> MixpanelInstance {
let instance = MixpanelInstance(apiToken: apiToken,
flushInterval: flushInterval,
name: instanceName,
optOutTrackingByDefault: optOutTrackingByDefault)
mainInstance = instance
readWriteLock.write {
instances[instanceName] = instance
}
return instance
}
#endif // os(OSX)
func getInstance(name instanceName: String) -> MixpanelInstance? {
var instance: MixpanelInstance?
readWriteLock.read {
instance = instances[instanceName]
}
if instance == nil {
Logger.warn(message: "no such instance: \(instanceName)")
return nil
}
return instance
}
func getMainInstance() -> MixpanelInstance? {
return mainInstance
}
func getAllInstances() -> [MixpanelInstance]? {
var allInstances: [MixpanelInstance]?
readWriteLock.read {
allInstances = Array(instances.values)
}
return allInstances
}
func setMainInstance(name instanceName: String) {
var instance: MixpanelInstance?
readWriteLock.read {
instance = instances[instanceName]
}
if instance == nil {
return
}
mainInstance = instance
}
func removeInstance(name instanceName: String) {
readWriteLock.write {
if instances[instanceName] === mainInstance {
mainInstance = nil
}
instances[instanceName] = nil
}
}
}