Mixpanel 不适用于 swift
Mixpanel does not work with swift
Cocoapods 尚未为 Swift 做好准备。当我在使用 Swift 的 iOS 项目中实现 Mixpanel 时,出现了几个错误。
如何解决这个问题并使 mixpanel 正常工作?
将这行代码添加到每个出错的文件中
#import <UIKit/UIKit.h>
还需要在链接的框架和库中添加这些:
libicucore.dylib
CFNetwork.framework
Security.framework
然后将其添加到您的 Bridging-Header.h 文件中:
#import "Mixpanel.h"
然后在你的appdelegate中添加这段代码:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
//other stuff here
Mixpanel.sharedInstanceWithToken("yourtokennumbergoeshere")
var mixPanel = Mixpanel.sharedInstance()
mixPanel.track("Finished Launching", properties: ["name1":"property1","name2":"property2"])
return true
}
使用这个非官方的 Swift 客户端!可能不如真实的好,但它可以用于基本跟踪。 https://github.com/soffes/Mixpanel
让 A/B 测试在 Swift 中工作并非易事,因为不支持宏。随意使用这个要点:
https://gist.github.com/ohad7/8ce12a432773fe3b1bf3
import Foundation
import Mixpanel
public class Tweaks : NSObject, MPTweakObserver {
public static let sharedInstance = Tweaks(tweaks: [ ExecuteDiskCleanup])
public static let ExecuteDiskCleanup = Tweak.Booln(name: "Cleanup-Disk", defaultValue:false)
private var values = [String:AnyObject]()
private let tweaks: [Tweak]
public init(tweaks: [Tweak]) {
self.tweaks = tweaks
let defaults = NSUserDefaults.standardUserDefaults()
for tweak in tweaks {
if let value: AnyObject = defaults.objectForKey(Tweaks.generateKey(tweak.name)) {
self.values[tweak.name] = value
println("Initialized Tweak \(tweak.name) with value: \(value)")
}
}
}
public func setup() {
tweaks.foreach(){ tweak in
let theTweak = MPTweak(name: tweak.name, andEncoding: "UTF-8")
theTweak.defaultValue = tweak.defaultValue
theTweak.addObserver(self)
MPTweakStore.sharedInstance().addTweak(theTweak)
}
Mixpanel.sharedInstance().checkForVariantsOnActive = true
Mixpanel.sharedInstance().joinExperiments()
}
public func get(tweaks: [Tweak]) -> [String:AnyObject] {
var result = [String:AnyObject]()
synced(values) {
tweaks.foreach(){ tweak in
result[tweak.name] = self.values[tweak.name]
}
}
return result
}
public func tweakDidChange(tweak: MPTweak) {
println("tweakDidChange Tweak \(tweak.name) current value :\(tweak.currentValue)")
synced(self.values) {
let localTweak = self.tweaks.filter{ [=10=].name == tweak.name}.first
if let localTweak = localTweak{
switch (localTweak) {
case .Booln:
self.values[tweak.name] = Bool(tweak.currentValue as? Int == 1)
default:
self.values[tweak.name] = tweak.currentValue
}
println("Tweak \(localTweak.name) -> \(self.values[localTweak.name])")
NSUserDefaults.standardUserDefaults().setObject(self.values[localTweak.name], forKey: Tweaks.generateKey(localTweak.name))
NSUserDefaults.standardUserDefaults().synchronize()
}
}
}
private class func generateKey(key: String) -> String {
return "mp_tweak_\(key)"
}
}
public enum Tweak {
case Str(name: String, defaultValue: String)
case Booln(name: String, defaultValue: Bool)
case Integer(name: String, defaultValue: Int)
case Flt(name: String, defaultValue: Float)
var name : String {
switch (self) {
case let .Str(n, d): return n
case let .Booln(n, d): return n
case let .Integer(n, d): return n
case let .Flt(n, d): return n
}
}
var defaultValue : AnyObject {
switch (self) {
case let .Str(n, d): return d
case let .Booln(n, d): return d
case let .Integer(n, d): return d
case let .Flt(n, d): return d
}
}
public func get<T>() -> T? {
return get(self.defaultValue as? T)
}
public func get<T>(defaultValue: T?) -> T? {
var value = synced(Tweaks.sharedInstance.values){
return Tweaks.sharedInstance.values[self.name] as? T
}
return value != nil ? value : defaultValue
}
}
// Examples :
// public static let SomeIntegerZero = Tweak.Integer(name: "SomeIntegerZero", defaultValue:0)
// public static let SomeIntegerNonZero = Tweak.Integer(name: "SomeIntegerNonZero", defaultValue:6666)
// public static let SomeBooleanFalse = Tweak.Booln(name: "SomeBooleanFalse", defaultValue:false)
// public static let SomeBooleanTrue = Tweak.Booln(name: "SomeBooleanTrue", defaultValue:true)
// public static let SomeStringEmpty = Tweak.Str(name: "SomeEmptyString", defaultValue:"")
// public static let SomeStringFull = Tweak.Str(name: "SomeFullString", defaultValue:"full")
/*** Utilities - sync methods ***/
func synced<T>(lock: AnyObject, closure: () -> T) -> T {
objc_sync_enter(lock)
let result = closure()
objc_sync_exit(lock)
return result
}
func synced(lock: AnyObject, closure: () -> ()) {
objc_sync_enter(lock)
closure()
objc_sync_exit(lock)
}
将您的 #import "mixpanel.h"
更改为 #import "Mixpanel/Mixpanel.h"
看起来 Mixpanel 已经发布了一些官方文档:
https://mixpanel.com/blog/2015/08/17/community-tip-implement-mixpanel-in-swift-apps
我在 podfiles 和桥接头导入方面遇到了问题,但是 use_frameworks!上面的建议 link 非常适合我。
Cocoapods 尚未为 Swift 做好准备。当我在使用 Swift 的 iOS 项目中实现 Mixpanel 时,出现了几个错误。
如何解决这个问题并使 mixpanel 正常工作?
将这行代码添加到每个出错的文件中
#import <UIKit/UIKit.h>
还需要在链接的框架和库中添加这些:
libicucore.dylib
CFNetwork.framework
Security.framework
然后将其添加到您的 Bridging-Header.h 文件中:
#import "Mixpanel.h"
然后在你的appdelegate中添加这段代码:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
//other stuff here
Mixpanel.sharedInstanceWithToken("yourtokennumbergoeshere")
var mixPanel = Mixpanel.sharedInstance()
mixPanel.track("Finished Launching", properties: ["name1":"property1","name2":"property2"])
return true
}
使用这个非官方的 Swift 客户端!可能不如真实的好,但它可以用于基本跟踪。 https://github.com/soffes/Mixpanel
让 A/B 测试在 Swift 中工作并非易事,因为不支持宏。随意使用这个要点:
https://gist.github.com/ohad7/8ce12a432773fe3b1bf3
import Foundation
import Mixpanel
public class Tweaks : NSObject, MPTweakObserver {
public static let sharedInstance = Tweaks(tweaks: [ ExecuteDiskCleanup])
public static let ExecuteDiskCleanup = Tweak.Booln(name: "Cleanup-Disk", defaultValue:false)
private var values = [String:AnyObject]()
private let tweaks: [Tweak]
public init(tweaks: [Tweak]) {
self.tweaks = tweaks
let defaults = NSUserDefaults.standardUserDefaults()
for tweak in tweaks {
if let value: AnyObject = defaults.objectForKey(Tweaks.generateKey(tweak.name)) {
self.values[tweak.name] = value
println("Initialized Tweak \(tweak.name) with value: \(value)")
}
}
}
public func setup() {
tweaks.foreach(){ tweak in
let theTweak = MPTweak(name: tweak.name, andEncoding: "UTF-8")
theTweak.defaultValue = tweak.defaultValue
theTweak.addObserver(self)
MPTweakStore.sharedInstance().addTweak(theTweak)
}
Mixpanel.sharedInstance().checkForVariantsOnActive = true
Mixpanel.sharedInstance().joinExperiments()
}
public func get(tweaks: [Tweak]) -> [String:AnyObject] {
var result = [String:AnyObject]()
synced(values) {
tweaks.foreach(){ tweak in
result[tweak.name] = self.values[tweak.name]
}
}
return result
}
public func tweakDidChange(tweak: MPTweak) {
println("tweakDidChange Tweak \(tweak.name) current value :\(tweak.currentValue)")
synced(self.values) {
let localTweak = self.tweaks.filter{ [=10=].name == tweak.name}.first
if let localTweak = localTweak{
switch (localTweak) {
case .Booln:
self.values[tweak.name] = Bool(tweak.currentValue as? Int == 1)
default:
self.values[tweak.name] = tweak.currentValue
}
println("Tweak \(localTweak.name) -> \(self.values[localTweak.name])")
NSUserDefaults.standardUserDefaults().setObject(self.values[localTweak.name], forKey: Tweaks.generateKey(localTweak.name))
NSUserDefaults.standardUserDefaults().synchronize()
}
}
}
private class func generateKey(key: String) -> String {
return "mp_tweak_\(key)"
}
}
public enum Tweak {
case Str(name: String, defaultValue: String)
case Booln(name: String, defaultValue: Bool)
case Integer(name: String, defaultValue: Int)
case Flt(name: String, defaultValue: Float)
var name : String {
switch (self) {
case let .Str(n, d): return n
case let .Booln(n, d): return n
case let .Integer(n, d): return n
case let .Flt(n, d): return n
}
}
var defaultValue : AnyObject {
switch (self) {
case let .Str(n, d): return d
case let .Booln(n, d): return d
case let .Integer(n, d): return d
case let .Flt(n, d): return d
}
}
public func get<T>() -> T? {
return get(self.defaultValue as? T)
}
public func get<T>(defaultValue: T?) -> T? {
var value = synced(Tweaks.sharedInstance.values){
return Tweaks.sharedInstance.values[self.name] as? T
}
return value != nil ? value : defaultValue
}
}
// Examples :
// public static let SomeIntegerZero = Tweak.Integer(name: "SomeIntegerZero", defaultValue:0)
// public static let SomeIntegerNonZero = Tweak.Integer(name: "SomeIntegerNonZero", defaultValue:6666)
// public static let SomeBooleanFalse = Tweak.Booln(name: "SomeBooleanFalse", defaultValue:false)
// public static let SomeBooleanTrue = Tweak.Booln(name: "SomeBooleanTrue", defaultValue:true)
// public static let SomeStringEmpty = Tweak.Str(name: "SomeEmptyString", defaultValue:"")
// public static let SomeStringFull = Tweak.Str(name: "SomeFullString", defaultValue:"full")
/*** Utilities - sync methods ***/
func synced<T>(lock: AnyObject, closure: () -> T) -> T {
objc_sync_enter(lock)
let result = closure()
objc_sync_exit(lock)
return result
}
func synced(lock: AnyObject, closure: () -> ()) {
objc_sync_enter(lock)
closure()
objc_sync_exit(lock)
}
将您的 #import "mixpanel.h"
更改为 #import "Mixpanel/Mixpanel.h"
看起来 Mixpanel 已经发布了一些官方文档: https://mixpanel.com/blog/2015/08/17/community-tip-implement-mixpanel-in-swift-apps
我在 podfiles 和桥接头导入方面遇到了问题,但是 use_frameworks!上面的建议 link 非常适合我。