adstage
移动 SDK应用内事件

iOS

AdStage 应用内事件对接指南(iOS)

目录

  1. 概述
  2. 基本设置
  3. 类型安全的事件发送
  4. 标准事件目录
  5. 各事件类型示例
  6. 最佳实践
  7. 故障排查

概述

AdStage 应用内事件通过跟踪用户行为与应用事件,支持营销分析与优化。

主要功能

  • 全局上下文管理:用户/设备信息只需设置一次即可自动附带
  • 简洁的 API:仅凭事件名称与参数即可轻松发送
  • 自动会话跟踪:自动生成并管理会话 ID
  • 异步处理:网络通信不会阻塞 UI
  • 离线支持:网络恢复时自动重新发送

基本设置

CocoaPods 设置

Podfile

platform :ios, '15.0'
 
target 'YourApp' do
  use_frameworks!
  
  # AdStage SDK
  pod 'AdapterAdStage', '3.0.11'
end
 
post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'
    end
  end
end

安装:

pod install

2. SDK 初始化

import AdapterAdStage
 
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        
        // AdStage 初始化
        AdStageManager.shared.initialize(
            apiKey: "your-api-key-here",
            serverUrl: "https://api.adstage.app"
        )
        
        print("✅ AdStage SDK 初始化完成")
        
        return true
    }
}

3. Info.plist 设置

<!-- 网络使用权限 -->
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
</dict>

类型安全的事件发送

1. 最简单的方式

import AdapterAdStage
 
// 不带参数的事件
AdStageManager.shared.trackEvent(AdStageEvent.FirstOpen())
 
// 登录事件
AdStageManager.shared.trackEvent(
    AdStageEvent.Login(method: .email)
)

2. 购买事件(校验示例)

// ✅ GOOD: value 与 currency 一并提供
AdStageManager.shared.trackEvent(
    AdStageEvent.Purchase(
        value: 29.99,
        currency: "USD",
        transactionId: "TXN_123456"
    )
)
 
// ❌ BAD: 仅提供 value 时会编译报错!
AdStageManager.shared.trackEvent(
    AdStageEvent.Purchase(
        value: 29.99  // ❌ 错误:currency 为必填!
    )
)
 
// ✅ GOOD: 不带 currency,仅提供 transactionId
AdStageManager.shared.trackEvent(
    AdStageEvent.Purchase(
        transactionId: "TXN_123456"
    )
)

3. 商品查看

// 带参数
AdStageManager.shared.trackEvent(
    AdStageEvent.ProductDetailsView(
        itemId: "PROD_123",
        itemName: "Wireless Earbuds"
    )
)
 
// 不带参数
AdStageManager.shared.trackEvent(AdStageEvent.ProductListView())

4. 自定义事件(event_name 自动提升)

除标准事件外,发送应用特有的事件时请使用 AdStageEvent.Custom。 若参数中包含 event_name 键,该值会自动提升为实际的事件名称并保存到仪表板。

// 例:发送名为 'promotion_click' 的自定义事件
AdStageManager.shared.trackEvent(
    AdStageEvent.Custom(
        params: [
            "event_name": "promotion_click",
            "promotion_id": "summer_sale_2025",
            "screen": "home_banner"
        ]
    )
)
// 仪表板中会作为 "promotion_click" 事件收集
 
// 不带 event_name 的普通自定义事件
AdStageManager.shared.trackEvent(
    AdStageEvent.Custom(
        params: [
            "action": "button_click",
            "button_id": "promo_banner",
            "screen": "home",
            "timestamp": Date().timeIntervalSince1970
        ]
    )
)
// 仪表板中会作为 "custom" 事件收集
 
// Click、View 同样支持自由参数
AdStageManager.shared.trackEvent(
    AdStageEvent.Click(
        params: [
            "campaign_id": "SUMMER2025",
            "ad_group": "electronics"
        ]
    )
)

标准事件目录

AdStage SDK 提供 46 个标准事件。

📌 广告跟踪(4 个)

// 1. 广告点击
AdStageManager.shared.trackEvent(
    AdStageEvent.Click(
        params: ["campaign_id": "CAMP_123"]
    )
)
 
// 2. 广告展示
AdStageManager.shared.trackEvent(
    AdStageEvent.View(
        params: ["impression_id": "IMP_456"]
    )
)
 
// 3. 应用安装
AdStageManager.shared.trackEvent(AdStageEvent.Install())
 
// 4. 自定义事件(用 event_name 指定事件名称)
AdStageManager.shared.trackEvent(
    AdStageEvent.Custom(
        params: [
            "event_name": "promotion_click",
            "promotion_id": "summer_sale_2025"
        ]
    )
)

👤 用户生命周期(5 个)

// SignUpMethod 是 SDK 提供的 enum(请勿自行定义)
// 可用的值:.email, .google, .apple, .facebook, .kakao, .naver
 
// 1. 注册完成
AdStageManager.shared.trackEvent(
    AdStageEvent.SignUp(method: .google)
)
 
// 2. 注册开始
AdStageManager.shared.trackEvent(AdStageEvent.SignUpStart())
 
// 3. 登录
AdStageManager.shared.trackEvent(
    AdStageEvent.Login(method: .email)
)
 
// 4. 登出
AdStageManager.shared.trackEvent(AdStageEvent.Logout())
 
// 5. 应用首次启动
AdStageManager.shared.trackEvent(AdStageEvent.FirstOpen())

📄 内容查看(6 个)

// 1. 首页画面
AdStageManager.shared.trackEvent(AdStageEvent.HomeView())
 
// 2. 商品列表
AdStageManager.shared.trackEvent(
    AdStageEvent.ProductListView(itemCategory: "electronics")
)
 
// 3. 搜索结果
AdStageManager.shared.trackEvent(
    AdStageEvent.SearchResultView(searchTerm: "wireless headphones")
)
 
// 4. 商品详情
AdStageManager.shared.trackEvent(
    AdStageEvent.ProductDetailsView(
        itemId: "PROD_123",
        itemName: "Wireless Earbuds"
    )
)
 
// 5. 页面浏览(网页)
AdStageManager.shared.trackEvent(
    AdStageEvent.PageView(
        pageUrl: "https://example.com/products",
        pageTitle: "Products"
    )
)
 
// 6. 画面浏览(应用)
AdStageManager.shared.trackEvent(
    AdStageEvent.ScreenView(
        screenName: "product_detail",
        screenClass: "ProductDetailViewController"
    )
)

🛒 电子商务(8 个)

// 1. 加入购物车
AdStageManager.shared.trackEvent(
    AdStageEvent.AddToCart(
        value: 99000.0,
        currency: "KRW",
        items: [
            EcommerceItem(
                itemId: "PROD_123",
                itemName: "Wireless Earbuds",
                price: 99000.0,
                quantity: 1
            )
        ]
    )
)
 
// 2. 移出购物车
AdStageManager.shared.trackEvent(
    AdStageEvent.RemoveFromCart(
        value: 50000.0,
        currency: "KRW"
    )
)
 
// 3. 加入心愿单
AdStageManager.shared.trackEvent(
    AdStageEvent.AddToWishlist(
        itemId: "PROD_456",
        itemName: "Smart Watch"
    )
)
 
// 4. 填写支付信息
AdStageManager.shared.trackEvent(
    AdStageEvent.AddPaymentInfo(paymentType: "credit_card")
)
 
// 5. 开始结算
AdStageManager.shared.trackEvent(
    AdStageEvent.BeginCheckout(
        value: 150000.0,
        currency: "KRW"
    )
)
 
// 6. 购买完成 ⭐⭐⭐
AdStageManager.shared.trackEvent(
    AdStageEvent.Purchase(
        value: 129000.0,
        currency: "KRW",
        transactionId: "ORDER_20250105_001",
        tax: 12900.0,
        shipping: 3000.0,
        coupon: "SUMMER2025",
        items: [
            EcommerceItem(
                itemId: "PROD_123",
                itemName: "Wireless Earbuds",
                price: 126000.0,
                quantity: 1
            )
        ]
    )
)
 
// 7. 退款
AdStageManager.shared.trackEvent(
    AdStageEvent.Refund(
        transactionId: "ORDER_20250105_001",
        value: 129000.0,
        currency: "KRW"
    )
)

🎮 进度/成就(4 个)

// 1. 教程开始
AdStageManager.shared.trackEvent(
    AdStageEvent.TutorialBegin(
        params: ["tutorial_id": "intro"]
    )
)
 
// 2. 教程完成
AdStageManager.shared.trackEvent(
    AdStageEvent.TutorialComplete(
        params: ["duration_seconds": 120]
    )
)
 
// 3. 升级
AdStageManager.shared.trackEvent(
    AdStageEvent.LevelUp(
        level: 25,
        character: "warrior"
    )
)
 
// 4. 达成成就
AdStageManager.shared.trackEvent(
    AdStageEvent.Achievement(achievementId: "first_win")
)

💬 互动(3 个)

// 1. 搜索
AdStageManager.shared.trackEvent(
    AdStageEvent.Search(searchTerm: "gaming laptop")
)
 
// 2. 分享
AdStageManager.shared.trackEvent(
    AdStageEvent.Share(
        contentType: "product",
        method: "kakao"
    )
)
 
// 3. 应用内广告点击
AdStageManager.shared.trackEvent(
    AdStageEvent.AdClick(
        adPlatform: "admob",
        adFormat: "rewarded_video",
        adUnitName: "AD_12345"
    )
)

🎮 游戏专用(4 个)

// 1. 游戏进行
AdStageManager.shared.trackEvent(
    AdStageEvent.GamePlay(
        level: 10,
        levelName: "Dragon's Lair",
        character: "mage",
        contentType: "dungeon"
    )
)
 
// 2. 获得奖励
AdStageManager.shared.trackEvent(
    AdStageEvent.AcquireBonus(
        contentType: "reward",
        itemId: "ITEM_123",
        itemName: "Gold Chest",
        quantity: 1
    )
)
 
// 3. 选择游戏服务器
AdStageManager.shared.trackEvent(
    AdStageEvent.SelectGameServer(
        contentId: "SERVER_01",
        contentType: "pvp",
        itemName: "Asia Server"
    )
)
 
// 4. 补丁完成
AdStageManager.shared.trackEvent(
    AdStageEvent.CompletePatch(
        contentId: "PATCH_2.1.0",
        contentType: "update"
    )
)

📅 订阅/试用(3 个)

// 1. 开始免费试用
AdStageManager.shared.trackEvent(
    AdStageEvent.StartTrial(
        value: 9900.0,
        currency: "KRW",
        trialDays: 14
    )
)
 
// 2. 开始订阅
AdStageManager.shared.trackEvent(
    AdStageEvent.Subscribe(
        value: 9900.0,
        currency: "KRW",
        subscriptionId: "premium_monthly"
    )
)
 
// 3. 取消订阅
AdStageManager.shared.trackEvent(
    AdStageEvent.Unsubscribe(subscriptionId: "premium_monthly")
)

💰 虚拟货币(2 个)

// 1. 获得虚拟货币(点数)- 使用 AcquireBonus
AdStageManager.shared.trackEvent(
    AdStageEvent.AcquireBonus(
        contentType: "currency",
        itemName: "gold",
        quantity: 500
    )
)
 
// 2. 使用虚拟货币(点数)- 使用 SpendCredits
AdStageManager.shared.trackEvent(
    AdStageEvent.SpendCredits(
        value: 100.0,
        itemName: "health_potion"
    )
)

🎯 其他(7 个)

// 1. 登记日程
AdStageManager.shared.trackEvent(
    AdStageEvent.Schedule(
        params: ["event_type": "appointment"]
    )
)
 
// 2. 使用点数
AdStageManager.shared.trackEvent(
    AdStageEvent.SpendCredits(
        value: 10.0,
        itemName: "premium_feature"
    )
)
 
// 3. 查看推广(以 Custom 事件发送)
AdStageManager.shared.trackEvent(
    AdStageEvent.Custom(
        params: [
            "event_name": "view_promotion",
            "promotion_id": "PROMO_SUMMER",
            "promotion_name": "Summer Sale 2025",
            "creative_slot": "home_banner_1"
        ]
    )
)
 
// 4. 选择推广(以 Custom 事件发送)
AdStageManager.shared.trackEvent(
    AdStageEvent.Custom(
        params: [
            "event_name": "select_promotion",
            "promotion_id": "PROMO_SUMMER",
            "promotion_name": "Summer Sale 2025"
        ]
    )
)

各事件类型示例

1. 应用生命周期

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        
        // SDK 初始化
        AdStageManager.shared.initialize(
            apiKey: "your-api-key",
            serverUrl: "https://api.adstage.app"
        )
        
        // 首次启动事件由 SDK 自动发送
        print("✅ 应用启动")
        
        return true
    }
    
    func applicationDidEnterBackground(_ application: UIApplication) {
        print("📱 应用进入后台")
    }
    
    func applicationWillEnterForeground(_ application: UIApplication) {
        print("📱 应用进入前台")
    }
}

2. 用户认证

class AuthManager {
    
    // 注册
    func onSignUpComplete(method: String) {
        let signUpMethod: SignUpMethod
        switch method {
        case "email": signUpMethod = .email
        case "google": signUpMethod = .google
        case "apple": signUpMethod = .apple
        case "kakao": signUpMethod = .kakao
        case "naver": signUpMethod = .naver
        default: signUpMethod = .email
        }
        
        AdStageManager.shared.trackEvent(
            AdStageEvent.SignUp(method: signUpMethod)
        )
        
        print("✅ 注册完成: \(method)")
    }
    
    // 登录
    func onLoginSuccess(userId: String, method: String) {
        let loginMethod: SignUpMethod = method == "google" ? .google : .email
        
        AdStageManager.shared.trackEvent(
            AdStageEvent.Login(method: loginMethod)
        )
        
        print("✅ 登录: \(userId)")
    }
    
    // 登出
    func onLogout() {
        AdStageManager.shared.trackEvent(AdStageEvent.Logout())
        print("🚪 登出")
    }
}

3. 画面跟踪(BaseViewController 模式)

class BaseViewController: UIViewController {
    
    // 在子类中覆写
    var screenName: String {
        return String(describing: type(of: self))
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        trackScreenView()
    }
    
    private func trackScreenView() {
        AdStageManager.shared.trackEvent(
            AdStageEvent.ScreenView(
                screenName: screenName,
                screenClass: String(describing: type(of: self))
            )
        )
        
        print("📺 \(screenName)")
    }
}
 
// 使用示例
class HomeViewController: BaseViewController {
    override var screenName: String { "home" }
}
 
class ProductDetailViewController: BaseViewController {
    override var screenName: String { "product_detail" }
    var productId: String?
    
    func loadProduct(_ productId: String) {
        self.productId = productId
        // 数据加载中...
        
        // 商品详情查看事件
        AdStageManager.shared.trackEvent(
            AdStageEvent.ProductDetailsView(
                itemId: productId,
                itemName: product.name
            )
        )
    }
}

4. 电子商务完整流程

class EcommerceManager {
    
    // 1. 商品列表查看
    func trackProductList(category: String) {
        AdStageManager.shared.trackEvent(
            AdStageEvent.ProductListView(itemCategory: category)
        )
    }
    
    // 2. 搜索
    func trackSearch(query: String) {
        AdStageManager.shared.trackEvent(
            AdStageEvent.Search(searchTerm: query)
        )
    }
    
    // 3. 搜索结果查看
    func trackSearchResults(query: String) {
        AdStageManager.shared.trackEvent(
            AdStageEvent.SearchResultView(searchTerm: query)
        )
    }
    
    // 4. 商品详情查看
    func trackProductView(product: Product) {
        AdStageManager.shared.trackEvent(
            AdStageEvent.ProductDetailsView(
                itemId: product.id,
                itemName: product.name
            )
        )
    }
    
    // 5. 加入购物车
    func trackAddToCart(product: Product, quantity: Int) {
        let item = EcommerceItem(
            itemId: product.id,
            itemName: product.name,
            price: product.price,
            quantity: quantity
        )
        
        AdStageManager.shared.trackEvent(
            AdStageEvent.AddToCart(
                value: product.price * Double(quantity),
                currency: "KRW",
                items: [item]
            )
        )
    }
    
    // 6. 加入心愿单
    func trackAddToWishlist(product: Product) {
        AdStageManager.shared.trackEvent(
            AdStageEvent.AddToWishlist(
                itemId: product.id,
                itemName: product.name
            )
        )
    }
    
    // 7. 开始结算
    func trackBeginCheckout(cart: Cart) {
        let items = cart.items.map { cartItem in
            EcommerceItem(
                itemId: cartItem.product.id,
                itemName: cartItem.product.name,
                price: cartItem.product.price,
                quantity: cartItem.quantity
            )
        }
        
        AdStageManager.shared.trackEvent(
            AdStageEvent.BeginCheckout(
                value: cart.totalAmount,
                currency: "KRW",
                items: items
            )
        )
    }
    
    // 8. 填写支付信息
    func trackAddPaymentInfo(paymentMethod: String) {
        AdStageManager.shared.trackEvent(
            AdStageEvent.AddPaymentInfo(paymentType: paymentMethod)
        )
    }
    
    // 9. 购买完成 ⭐⭐⭐
    func trackPurchase(order: Order) {
        let items = order.items.map { orderItem in
            EcommerceItem(
                itemId: orderItem.product.id,
                itemName: orderItem.product.name,
                price: orderItem.product.price,
                quantity: orderItem.quantity
            )
        }
        
        AdStageManager.shared.trackEvent(
            AdStageEvent.Purchase(
                value: order.totalAmount,
                currency: "KRW",
                transactionId: order.id,
                tax: order.tax,
                shipping: order.shippingFee,
                coupon: order.couponCode,
                items: items
            )
        )
        
        print("✅ 购买完成: \(order.id), \(order.totalAmount) 韩元")
    }
    
    // 10. 退款
    func trackRefund(order: Order) {
        AdStageManager.shared.trackEvent(
            AdStageEvent.Refund(
                transactionId: order.id,
                value: order.totalAmount,
                currency: "KRW"
            )
        )
    }
    
    // 11. 分享
    func trackShare(product: Product, method: String) {
        AdStageManager.shared.trackEvent(
            AdStageEvent.Share(
                contentType: "product",
                method: method
            )
        )
    }
}

5. 游戏事件

class GameEventManager {
    
    // 教程
    func trackTutorialBegin(tutorialId: String) {
        AdStageManager.shared.trackEvent(
            AdStageEvent.TutorialBegin(
                params: ["tutorial_id": tutorialId]
            )
        )
    }
    
    func trackTutorialComplete(tutorialId: String, duration: TimeInterval) {
        AdStageManager.shared.trackEvent(
            AdStageEvent.TutorialComplete(
                params: [
                    "tutorial_id": tutorialId,
                    "duration_seconds": Int(duration)
                ]
            )
        )
    }
    
    // 等级
    func trackLevelUp(level: Int, character: String) {
        AdStageManager.shared.trackEvent(
            AdStageEvent.LevelUp(
                level: level,
                character: character
            )
        )
    }
    
    // 成就
    func trackAchievement(achievementId: String) {
        AdStageManager.shared.trackEvent(
            AdStageEvent.Achievement(achievementId: achievementId)
        )
    }
    
    // 游戏进行
    func trackGameStart(level: Int, levelName: String, character: String) {
        AdStageManager.shared.trackEvent(
            AdStageEvent.GamePlay(
                level: level,
                levelName: levelName,
                character: character,
                contentType: "pvp"
            )
        )
    }
    
    // 获得奖励
    func trackBonusAcquired(itemId: String, itemName: String, quantity: Int) {
        AdStageManager.shared.trackEvent(
            AdStageEvent.AcquireBonus(
                contentType: "reward",
                itemId: itemId,
                itemName: itemName,
                quantity: quantity
            )
        )
    }
    
    // 获得虚拟货币(点数)- 使用 AcquireBonus
    func trackEarnCurrency(currencyName: String, amount: Int) {
        AdStageManager.shared.trackEvent(
            AdStageEvent.AcquireBonus(
                contentType: "currency",
                itemName: currencyName,
                quantity: amount
            )
        )
    }
    
    // 使用虚拟货币(点数)- 使用 SpendCredits
    func trackSpendCurrency(currencyName: String, amount: Double, itemName: String) {
        AdStageManager.shared.trackEvent(
            AdStageEvent.SpendCredits(
                value: amount,
                itemName: itemName
            )
        )
    }
}

最佳实践

1. 活用 Extension

// UIViewController+AdStage.swift
extension UIViewController {
    func trackScreen() {
        let screenName = String(describing: type(of: self))
            .replacingOccurrences(of: "ViewController", with: "")
            .lowercased()
        
        AdStageManager.shared.trackEvent(
            AdStageEvent.ScreenView(
                screenName: screenName,
                screenClass: String(describing: type(of: self))
            )
        )
    }
}
 
// 使用
class ProfileViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        trackScreen()  // ✅ 简单!
    }
}

2. 在 ViewModel 中跟踪事件

class ProductViewModel: ObservableObject {
    
    @Published var product: Product?
    
    func loadProduct(productId: String) {
        Task {
            do {
                let product = try await repository.getProduct(productId)
                self.product = product
                
                // 商品查看事件
                AdStageManager.shared.trackEvent(
                    AdStageEvent.ProductDetailsView(
                        itemId: product.id,
                        itemName: product.name
                    )
                )
                
            } catch {
                print("Failed to load product: \(error)")
            }
        }
    }
    
    func addToCart(product: Product, quantity: Int) {
        Task {
            do {
                try await repository.addToCart(product, quantity: quantity)
                
                let item = EcommerceItem(
                    itemId: product.id,
                    itemName: product.name,
                    price: product.price,
                    quantity: quantity
                )
                
                AdStageManager.shared.trackEvent(
                    AdStageEvent.AddToCart(
                        value: product.price * Double(quantity),
                        currency: "KRW",
                        items: [item]
                    )
                )
                
            } catch {
                print("Failed to add to cart: \(error)")
            }
        }
    }
}

3. 在 SwiftUI 中使用

import SwiftUI
import AdapterAdStage
 
struct ProductDetailView: View {
    let productId: String
    @StateObject private var viewModel = ProductViewModel()
    
    var body: some View {
        VStack {
            // UI...
            
            Button("加入购物车") {
                viewModel.addToCart(viewModel.product, quantity: 1)
                
                // 按钮点击事件
                AdStageManager.shared.trackEvent(
                    AdStageEvent.Custom(
                        params: [
                            "action": "add_to_cart_button",
                            "product_id": productId
                        ]
                    )
                )
            }
        }
        .onAppear {
            viewModel.loadProduct(productId: productId)
            
            // 画面浏览事件
            AdStageManager.shared.trackEvent(
                AdStageEvent.ScreenView(
                    screenName: "product_detail",
                    screenClass: "ProductDetailView"
                )
            )
        }
    }
}

4. 事件封装类

class AnalyticsManager {
    
    static let shared = AnalyticsManager()
    private init() {}
    
    func trackScreen(_ screenName: String, screenClass: String? = nil) {
        AdStageManager.shared.trackEvent(
            AdStageEvent.ScreenView(
                screenName: screenName,
                screenClass: screenClass
            )
        )
        print("📺 Screen: \(screenName)")
    }
    
    func trackPurchase(_ order: Order) {
        let items = order.items.map {
            EcommerceItem(
                itemId: $0.product.id,
                itemName: $0.product.name,
                price: $0.product.price,
                quantity: $0.quantity
            )
        }
        
        AdStageManager.shared.trackEvent(
            AdStageEvent.Purchase(
                value: order.totalAmount,
                currency: "KRW",
                transactionId: order.id,
                items: items
            )
        )
        
        print("💰 Purchase: \(order.id)")
    }
    
    func trackError(_ error: Error, context: String) {
        AdStageManager.shared.trackEvent(
            AdStageEvent.Custom(
                params: [
                    "event_type": "error",
                    "error_message": error.localizedDescription,
                    "context": context
                ]
            )
        )
        print("❌ Error: \(context) - \(error)")
    }
}

5. 性能优化:Throttling

class ThrottledEventTracker {
    private var lastTrackTimes: [String: TimeInterval] = [:]
    private let throttleInterval: TimeInterval = 2.0  // 2 秒
    
    func trackEvent(_ event: AdStageEventProtocol) {
        let eventKey = event.eventName
        let now = Date().timeIntervalSince1970
        let lastTime = lastTrackTimes[eventKey] ?? 0
        
        if now - lastTime >= throttleInterval {
            AdStageManager.shared.trackEvent(event)
            lastTrackTimes[eventKey] = now
        } else {
            print("⏱️ Throttled: \(eventKey)")
        }
    }
}
 
// 使用(滚动事件等)
let throttledTracker = ThrottledEventTracker()
 
func scrollViewDidScroll(_ scrollView: UIScrollView) {
    throttledTracker.trackEvent(
        AdStageEvent.Custom(
            params: [
                "action": "scroll",
                "offset_y": scrollView.contentOffset.y
            ]
        )
    )
}

迁移示例

// 1. 基本事件
// OLD: EventTrackingManager.shared.trackEvent(...)
// NEW:
AdStageManager.shared.trackEvent(AdStageEvent.FirstOpen())
 
// 2. 登录
// NEW:
AdStageManager.shared.trackEvent(AdStageEvent.Login(method: .email))
 
// 3. 画面浏览
// NEW:
AdStageManager.shared.trackEvent(AdStageEvent.ScreenView(screenName: "home"))
 
// 4. 自定义
// NEW:
AdStageManager.shared.trackEvent(
    AdStageEvent.Custom(params: ["action": "click"])
)

故障排查

1. 编译报错:"currency 参数为必填"

问题:

// ❌ 错误
AdStageManager.shared.trackEvent(
    AdStageEvent.Purchase(value: 9900.0)
)

解决:

// ✅ 添加 currency(ISO 4217,3 位)
AdStageManager.shared.trackEvent(
    AdStageEvent.Purchase(
        value: 9900.0,
        currency: "KRW"
    )
)

2. Xcode 自动补全不生效

解决:

  1. Clean Build Folder:Product → Clean Build Folder (⇧⌘K)
  2. 删除 Derived Data:~/Library/Developer/Xcode/DerivedData
  3. 重新安装 Pod:
pod deintegrate
pod install

3. 货币代码校验错误

// ❌ 2 位代码
AdStageEvent.Purchase(value: 100.0, currency: "KR")
// ValidationException: "Currency must be 3-letter ISO 4217 code"
 
// ✅ 3 位 ISO 4217 代码
AdStageEvent.Purchase(value: 100.0, currency: "KRW")  // 韩元
AdStageEvent.Purchase(value: 100.0, currency: "USD")  // 美元
AdStageEvent.Purchase(value: 100.0, currency: "JPY")  // 日元

4. SwiftUI Preview 冲突

问题: Preview 中出现 AdStageManager 初始化错误

解决:

#if DEBUG
struct ProductDetailView_Previews: PreviewProvider {
    static var previews: some View {
        ProductDetailView(productId: "PROD_123")
            .onAppear {
                // Preview 中不进行初始化
                if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == nil {
                    AdStageManager.shared.initialize(
                        apiKey: "test-key",
                        serverUrl: "https://api.adstage.app"
                    )
                }
            }
    }
}
#endif

5. 查看调试日志

SDK 会自动将初始化及事件发送过程的日志输出到控制台。 无需额外设置调试模式,即可直接在 Xcode 控制台中查看。

控制台筛选:

# Xcode Console
filter: AdStage   (或 ADSTAGE)

参考资料

标准参考


FAQ

Q: 自定义事件该如何发送?
A: 使用 AdStageEvent.Custom(params: [...])

Q: 与 Android SDK 兼容吗?
A: 是的,v3.0 支持与 Android SDK 完全相同的 46 个事件。

Q: 可以在 SwiftUI 中使用吗?
A: 可以,通过 ObservableObject 模式完整支持。


支持

联系方式:


© 2025 NBase. All rights reserved.

目录