Signed-off-by: Haoyi <haoyi.zhang@castbox.fm>
main 0.4.3
Haoyi 2025-08-08 18:12:14 +08:00
parent 0ad881ca66
commit 8163f171d2
14 changed files with 244 additions and 18 deletions

View File

@ -1,3 +1,48 @@
## v0.4.3
- fix
- 事件参数值字符串中包含“”单引号sql报错
- feature
- 增加事件参数
- deviceInfo.appsflyerId
- 增加设置appsflyerId接口
- setAppFlyersId(_ appFlyersId: String?) -> Void
## v0.4.2
- fix
- 临时回滚 0.4.0排查solitare collection ATP DAU下降问题。
## v0.4.1
- fix
- x.0的数值类型转换成整型问题
## v0.4.0
- feature
- 支持 AppExtension 上报打点
- 如在AppExtension 中使用需在Podfile 中添加以下代码:
```swift
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
if target.name == 'GuruAnalyticsLib'
config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = 'NO'
end
end
end
```
## v0.3.9
- feature
- 增加事件参数
- deviceInfo.guruAnalyticsVersion
- deviceInfo.gurusdkVersion
- 增加设置中台版本接口
- 初始化方法增加guruSDKVersion参数 initializeLib(..., guruSDKVersion: String)
- setGuruSDKVersion(_ version: String) -> Void
## v0.3.8.1
- fix
- x.0的数值类型转换成整型问题
## v0.3.8
- fix
- 隐私文件增加divice id声明
@ -15,6 +60,10 @@
- deviceInfo.sdkVersion
- info.vendorId
## v0.3.6.1
- fix:
- 更新privacy manifest文件移除tracking domains下的空条目。
## v0.3.6
- fix:
- 增加第三方依赖库版本约束

View File

@ -370,6 +370,8 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 69MW7VVKA9;
INFOPLIST_FILE = GuruAnalytics/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = GuruAnalytics;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@ -390,6 +392,8 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 69MW7VVKA9;
INFOPLIST_FILE = GuruAnalytics/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = GuruAnalytics;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",

View File

@ -27,7 +27,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
batchLimit: 25,
initializeTimeout: 5,
saasXAPPID: "test_app_id",
saasXDEVICEINFO: "appIdentifier=test.app.example;appVersion=1.0;deviceType=apple;deviceCountry=CN")
saasXDEVICEINFO: "appIdentifier=test.app.example;appVersion=1.0;deviceType=apple;deviceCountry=CN",
guruSDKVersion: "1.0.0")
GuruAnalytics.setUserID("100004")
GuruAnalytics.setAdjustId("xsdfal021sxasdfl")
GuruAnalytics.setDeviceId(UUID().uuidString)

View File

@ -1,7 +1,31 @@
import UIKit
import Foundation
var greeting = "Hello, playground"
let sss = ["1", "2", "3"].map({ "'\($0)'"
}).joined(separator: ",")
print("value in (\(sss))")
let number = NSNumber(7.0)
let number2 = NSNumber(7)
print("number is double: \(number is Double)")
print("number is int: \(number is Int)")
print("number value: \(number)")
print("number type: \(number.objCType)")
extension NSNumber {
var type: CFNumberType {
return CFNumberGetType(self as CFNumber)
}
}
print("number type: \(number.type)")
print("number2 type: \(number2.type)")
let number3 = 7.0
print("number3 is Double: \(number3 is Double)")
print("number3 is Int: \(number3 is Int)")
print("number3 is NSNumber: \(number3 is NSNumber)")

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@ -23,15 +23,31 @@ class ViewController: UIViewController {
@IBAction func setFirebaseId(_ sender: Any) {
GuruAnalytics.setFirebaseId("2312:3XSFA0211231")
GuruAnalytics.setAppFlyersId("app_flyers_id:133323")
}
@IBAction func create(_ sender: Any) {
GuruAnalytics.setScreen("home")
GuruAnalytics.logEvent("crate_clk_" + String(Int(Date().timeIntervalSince1970)),
parameters: ["category": "category_\(Int.random(in: 0...100000))",
"int_v_test": 2147483647, "double_v_test": 200.1,
"int_v_test": 2147483647, "double_v_test_1": 200.1,
"double_v_test_2": NSNumber(7.00),
"double_v_test_3": 7.00,
"string_v_test": "400",
"long_v_test": Int64(1)])
"long_v_test": Int64(1),
"long_v_test2": Int64.max,
"long_v_test3": Int64.min,
"value": 0.0])
GuruAnalytics.logEvent("spend_virtual_currency",
parameters: ["theme_name": "theme_bg_0029",
"theme_category": "theme",
"virtural_currency_name": "coins",
"value": 100,
"balance": 33810,
"scene": "theme",
"level_name": "Instance of I'm 'SettingIntDat'",
])
}
@IBAction func deleteItem(_ sender: Any) {

View File

@ -7,7 +7,7 @@ platform :ios, '11.0'
target 'GuruAnalytics_Example' do
pod 'GuruAnalyticsLib', :path => '../'
# pod 'GuruAnalyticsLib', '0.3.8'
# pod 'GuruAnalyticsLib', '0.4.2'
end
post_install do |installer|

View File

@ -34,7 +34,8 @@ public class GuruAnalytics: NSObject {
initializeTimeout: Double = 5,
saasXAPPID: String,
saasXDEVICEINFO: String,
loggerDebug: Bool = true) {
loggerDebug: Bool = true,
guruSDKVersion: String) {
Self.uploadPeriodInSecond = uploadPeriodInSecond
Self.batchLimit = batchLimit
Self.eventExpiredSeconds = eventExpiredSeconds
@ -42,6 +43,7 @@ public class GuruAnalytics: NSObject {
Self.saasXAPPID = saasXAPPID
Self.saasXDEVICEINFO = saasXDEVICEINFO
Self.loggerDebug = loggerDebug
Constants.guruSDKVersion = guruSDKVersion
_ = Manager.shared
}
@ -81,6 +83,12 @@ public class GuruAnalytics: NSObject {
setUserProperty(firebaseId, forName: .firebaseId)
}
/// appsflyerId
@objc
public class func setAppFlyersId(_ appFlyersId: String?) {
setUserProperty(appFlyersId, forName: .appsflyerId)
}
/// screen name
@objc
public class func setScreen(_ name: String) {
@ -155,4 +163,9 @@ public class GuruAnalytics: NSObject {
enableUpload = isOn
}
///
@objc
public class func setGuruSDKVersion(_ version: String) -> Void {
Constants.guruSDKVersion = version
}
}

View File

@ -157,21 +157,35 @@ extension Entity {
}
static func normalizeValue(_ value: Any) -> EventValue {
var preprocessedValue = value
if let val = preprocessedValue as? NSNumber {
preprocessedValue = val.numricValue
}
let eventValue: EventValue
if let value = value as? String {
eventValue = Entity.EventValue(stringValue: String(value.prefix(maxParameterStringValueLength)))
} else if let value = value as? Int {
if let value = preprocessedValue as? String {
eventValue = Entity.EventValue(stringValue: normalizeStringValue(String(value.prefix(maxParameterStringValueLength))))
} else if let value = preprocessedValue as? Int {
eventValue = Entity.EventValue(longValue: Int64(value))
} else if let value = value as? Int64 {
} else if let value = preprocessedValue as? Int64 {
eventValue = Entity.EventValue(longValue: value)
} else if let value = value as? Double {
} else if let value = preprocessedValue as? Double {
eventValue = Entity.EventValue(doubleValue: value)
} else {
eventValue = Entity.EventValue(stringValue: String("\(value)".prefix(maxParameterStringValueLength)))
eventValue = Entity.EventValue(stringValue: normalizeStringValue(String("\(value)".prefix(maxParameterStringValueLength))))
}
return eventValue
}
static func normalizeStringValue(_ value: String) -> String {
let normalizedString = value.replacingOccurrences(of: "'", with: "''")
cdPrint("original string value: \(value)")
cdPrint("normalized string value: \(normalizedString)")
return normalizedString
}
static func normalizeKey(_ key: String) -> String? {
var mutableKey = key
@ -205,6 +219,8 @@ extension Entity {
let adId: String?
///pseudo_id
let firebaseId: String?
///appsFlyerId
let appsflyerId: String?
///IDFV
let vendorId: String? = UIDevice().identifierForVendor?.uuidString
@ -216,6 +232,7 @@ extension Entity {
case adId
case firebaseId
case vendorId
case appsflyerId
}
}

View File

@ -270,7 +270,8 @@ internal extension Manager {
deviceId: userProperty.removeValue(forKey: PropertyName.deviceId.rawValue),
adjustId: userProperty.removeValue(forKey: PropertyName.adjustId.rawValue),
adId: userProperty.removeValue(forKey: PropertyName.adId.rawValue),
firebaseId: userProperty.removeValue(forKey: PropertyName.firebaseId.rawValue)
firebaseId: userProperty.removeValue(forKey: PropertyName.firebaseId.rawValue),
appsflyerId: userProperty.removeValue(forKey: PropertyName.appsflyerId.rawValue)
)
let event = try Entity.Event(timestamp: timestamp,

View File

@ -18,6 +18,7 @@ internal extension GuruAnalytics {
case firebaseId
case screen = "screen_name"
case firstOpenTime = "first_open_time"
case appsflyerId
}
///built-in events

View File

@ -26,7 +26,7 @@ internal struct Constants {
return shortVersion
}()
private static let sdkVersion: String = {
private static let guruAnalyticsSDKVersion: String = {
guard let infoDict = Bundle(for: Manager.self).infoDictionary,
let currentVersion = infoDict["CFBundleShortVersionString"] as? String else {
return ""
@ -34,6 +34,9 @@ internal struct Constants {
return currentVersion
}()
///
static var guruSDKVersion: String = "";
private static let preferredLocale: Locale = {
guard let preferredIdentifier = Locale.preferredLanguages.first else {
return Locale.current
@ -92,7 +95,8 @@ internal struct Constants {
"screenW": Int(screenSize.w),
"osVersion": systemVersion,
"language" : languageCode,
"sdkVersion" : sdkVersion,
"guruAnalyticsVersion" : guruAnalyticsSDKVersion,
"gurusdkVersion" : guruSDKVersion,
]
}
@ -102,6 +106,50 @@ internal struct Constants {
/// - returns: raw `String` of device type, e.g. iPhone5,1
///
private static func hardwareString() -> String {
var name: [Int32] = [CTL_HW, HW_MACHINE]
var size: size_t = 0
// 🛡 1
guard sysctl(&name, 2, nil, &size, nil, 0) == 0,
size > 0 && size < 256 else {
return "iPhone14,1" //
}
// 🛡 2
let bufferSize = Int(size) + 1
var hw_machine = [CChar](repeating: 0, count: bufferSize)
var actualSize = size
// 🛡 3
guard sysctl(&name, 2, &hw_machine, &actualSize, nil, 0) == 0 else {
return "iPhone14,1" //
}
// 🛡 4null
let safeIndex = min(Int(actualSize), bufferSize - 1)
hw_machine[safeIndex] = 0
var hardware: String = String(cString: hw_machine)
// 🛡 5
if hardware.isEmpty {
return "iPhone14,1" //
}
// Check for simulator
if hardware == "x86_64" || hardware == "i386" || hardware == "arm64" {
if let deviceID = ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"] {
hardware = deviceID
} else {
hardware = "Simulator"
}
}
return hardware
}
//
private static func hardwareStringError() -> String {
var name: [Int32] = [CTL_HW, HW_MACHINE]
var size: Int = 2
sysctl(&name, 2, nil, &size, nil, 0)
@ -120,6 +168,8 @@ internal struct Constants {
return hardware
}
/// This method returns the Platform enum depending upon harware string
///
///

View File

@ -0,0 +1,43 @@
//
// Untitled.swift
// Pods
//
// Created by mayue on 2025/1/14.
//
extension NSNumber {
var valueType: CFNumberType {
return CFNumberGetType(self as CFNumber)
}
var numricValue: Any {
switch valueType {
case .sInt8Type,
.sInt16Type,
.sInt32Type,
.charType,
.shortType,
.intType,
.longType,
.cfIndexType,
.nsIntegerType:
return intValue;
case
.sInt64Type,
.longLongType:
return int64Value;
case .float32Type,
.float64Type,
.floatType,
.doubleType,
.cgFloatType,
.maxType:
return doubleValue;
@unknown default:
return doubleValue;
}
}
}

View File

@ -8,7 +8,7 @@
Pod::Spec.new do |s|
s.name = 'GuruAnalyticsLib'
s.version = '0.3.8'
s.version = '0.4.4'
s.summary = 'A short description of GuruAnalytics.'
# This description is used to generate tags and improve search results.
@ -25,7 +25,7 @@ TODO: Add long description of the pod here.
# s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'devSC' => 'xiaochong2154@163.com' }
s.source = { :git => 'git@github.com:castbox/GuruAnalytics_iOS.git', :tag => s.version.to_s }
s.source = { :git => 'git@git.chengdu.pundit.company:castbox/GuruAnalytics_iOS.git', :tag => s.version.to_s }
# s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
s.ios.deployment_target = '11.0'