Skip to content

iOS SDK Initialization

Initialization Timing

The UjuAd SDK must be initialized in the didFinishLaunchingWithOptions method of AppDelegate to ensure initialization is completed at app launch, preparing for subsequent ad loading.

The iOS SDK uses a two-phase initialization mechanism to meet privacy compliance requirements:

  1. Phase 1 (initialize): Synchronously saves configuration. No network/device operations, no privacy data collection.
  2. Phase 2 (start): Asynchronously executes initialization, collects device information and fetches strategies, then calls back listener upon completion.

Basic Initialization

1. Complete Two-Phase Initialization in AppDelegate

swift
import UIKit
import UjuAdCore

@main
final class AppDelegate: UIResponder, UIApplicationDelegate {

    private let initListener = AppInitListener()

    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        // 阶段 1:构造配置 + initialize(同步,无网络/设备操作,可安全在主线程调用)
        let config = UjuAdInitConfig.create(
            appId: "YOUR_APP_ID",                       // 必填,优聚智汇平台分配
            appKey: "YOUR_APP_KEY",                     // 必填,RSA 公钥(后台分配,原样传入)
            channel: "AppStore",                        // 渠道,默认 AppStore
            isDebug: true,                              // 调试模式,发布前改为 false
            region: .domestic,                          // 服务区域:.domestic(国内)/ .singapore(海外)
            rsaPublicKey: "YOUR_RSA_PUBLIC_KEY"         // For server-side communication encryption (optional, empty means no encryption)
        )
        UjuAdCore.shared.initialize(application, config: config)

        // 阶段 2:异步启动 SDK(内部按多步骤执行,完成后回调 listener)
        UjuAdCore.shared.start(initListener)

        return true
    }
}

// MARK: - InitListener

final class AppInitListener: BaseInitListener, @unchecked Sendable {
    func onInitSuccess() {
        // SDK 启动成功,可以开始加载广告
        print("SDK 初始化成功(version=\(UjuAdCore.shared.getVersion()))")
    }

    func onInitFailed(error: UjuException) {
        // SDK 初始化失败
        print("SDK 初始化失败: \(error.description)")
    }
}

Callback Thread

onInitSuccess / onInitFailed are called on the MainActor (main thread) and can safely update UI.

2. Configuration Parameters (UjuAdInitConfig.create)

UjuAdInitConfig's init is private. You must construct it via the create(...) factory method.

ParameterTypeRequiredDefaultDescription
appIdStringYesApp ID, obtained from the UjuAd backend
appKeyStringYesRSA public key, obtained from the backend, pass as-is, do not modify
channelStringNo"AppStore"Channel identifier, used for analytics and revenue sharing
subChannelStringNo""Sub-channel
isDebugBoolNofalseDebug mode, recommended during development (outputs SDK internal NSLog)
wxAppIdString?NonilWeChat AppId, used for Deeplink attribution
privacyConfigUjuPrivacyConfigNoUjuPrivacyConfig()Privacy authorization configuration
personalizationUjuPersonalizedConfigNoUjuPersonalizedConfig()Personalized recommendation configuration
presetStrategyFileNameString?NonilPreset strategy file name, e.g. "placement_config.json"
regionUjuAdRegionNo.domesticService region; the SDK derives service hosts based on this
rsaPublicKeyStringNo""RSA public key (PEM), used for server-side communication encryption; empty means no encryption
loggerBackendUjuLoggerBackendNo.nsLogLog backend type (.nsLog / .osLog / .fileLog / .hybrid)
debugBidRequestBoolNofalseWhether to output BidRequest JSON debug logs (only effective when isDebug=true)
crashReportingEnabledBoolNotrueWhether to enable crash reporting

region Description

Integrators only need to select region (.domestic for China / .singapore for overseas). All service addresses are automatically derived by the SDK based on region and are not exposed to integrators. Do not attempt to configure server addresses yourself.

3. UjuAdRegion Enum

Enum ValueDescription
.domesticChina
.singaporeOverseas
swift
let region = UjuAdCore.shared.getRegion()  // .domestic / .singapore

Privacy Configuration UjuPrivacyConfig

Describes the scope of privacy data the SDK is allowed to collect. All fields default to false (strictest privacy compliance). The integrator must explicitly enable authorization fields.

FieldTypeDefaultDescription
canUseIDFABoolfalseWhether IDFA usage is allowed (requires ATT authorization)
canUseIDFVBoolfalseWhether IDFV usage is allowed
canUseLocationBoolfalseWhether location usage is allowed
canUseImeiBoolfalseWhether IMEI usage is allowed (iOS typically does not allow; field retained for compatibility)
canUseOaidBoolfalseWhether OAID usage is allowed (iOS has no equivalent; field retained for compatibility)
canUseMacBoolfalseWhether MAC address usage is allowed (iOS typically does not allow; field retained for compatibility)
swift
let privacyConfig = UjuPrivacyConfig(
    canUseIDFA: true,       // 需 ATT 授权
    canUseIDFV: true,
    canUseLocation: true
)
let config = UjuAdInitConfig.create(
    appId: "YOUR_APP_ID",
    appKey: "YOUR_APP_KEY",
    privacyConfig: privacyConfig
)

Privacy Compliance

It is recommended to enable canUseIDFA / canUseLocation and other authorization fields only after obtaining explicit user consent. When not enabled, the SDK still works, but attribution accuracy may decrease.

Personalization Configuration UjuPersonalizedConfig

Complies with the Personal Information Protection Law. All fields default to false (strictest compliance). The integrator must explicitly enable them.

FieldTypeDefaultDescription
personalizedRecommendBoolfalseWhether personalized recommendations are allowed
programmaticRecommendedBoolfalseWhether programmatic recommendations are allowed
swift
let personalization = UjuPersonalizedConfig(
    personalizedRecommend: true,
    programmaticRecommended: true
)
let config = UjuAdInitConfig.create(
    appId: "YOUR_APP_ID",
    appKey: "YOUR_APP_KEY",
    personalization: personalization
)

Update Channel Information

After SDK initialization is complete, you can dynamically update the channel and sub-channel via updateChannel:

swift
UjuAdCore.shared.updateChannel(channel: "新渠道", subChannel: "新子渠道")

Initialization State Check

swift
// 是否已完成 initialize(第一阶段)
if UjuAdCore.shared.isSdkInitialized() {
    // 已完成 init,可调用 start
}

// 获取初始化状态枚举
let state = UjuAdCore.shared.getInitializeState()
switch state {
case .idle: print("未初始化")
case .initializing: print("初始化中")
case .initialized: print("已初始化")
case .failed: print("初始化失败")
}

UjuAdInitStatus Enum

Enum ValueDescription
.idleIdle state, start() has not been called yet
.initializingInitializing, collecting device information and fetching strategies
.initializedInitialized, ads can be loaded normally
.failedInitialization failed

SDK Other Public Methods

In addition to initialize / start / updateChannel, UjuAdCore provides the following public methods:

MethodReturn ValueDescription
isSdkInitialized()BoolWhether initialize (phase 1) has completed
getInitializeState()UjuAdInitStatusGet initialization state enum
getVersion()StringGet SDK version number (currently 3.4.2)
getAppId()StringGet current app ID
getRegion()UjuAdRegionGet service region
getIDFA()StringGet IDFA (returns empty string if unauthorized)
getIDFV()StringGet IDFV
requestAttAuthorization(completion:)VoidRequest ATT authorization
requestLocation(completion:)VoidOne-time location request
setIDFA(_:)VoidDeveloper-injected IDFA
setUserInfo(_:)VoidInject user information
setLocation(_:)VoidInject location information
registerAdapterFactory(_:)BoolRegister a single adapter factory
destroy()VoidRelease SDK resources
getConnectionSnapshots()[ConnectionSnapshot]Diagnostic: Get gRPC connection pool snapshots (for debugging, not needed for normal integration)
getConnectionCount()IntDiagnostic: Get current connection count
getRecentConnectionEventLogs(limit:)[ConnectionEventLog]Diagnostic: Get recent connection event logs
swift
// 获取 SDK 版本号
print("SDK 版本: \(UjuAdCore.shared.getVersion())")  // 3.4.2

Destroy SDK (Optional)

Call when the app exits or when you need to reset the SDK:

swift
UjuAdCore.shared.destroy()

Note: After destroy, if you need to use the SDK again, you must call initialize + start again.

FAQ

Q: What to do if initialization fails?

A: Possible causes:

  • Whether appId / appKey (RSA public key) is correct
  • Whether region is selected correctly (.domestic for China / .singapore for overseas)
  • Whether the network connection is normal
  • Enable isDebug = true and check the console logs for the specific failure reason

Q: Why don't I need to configure server addresses?

A: Integrators only need to select region. All service hosts are automatically derived by the SDK based on region and are not exposed to integrators. This is a fixed internal platform configuration and is not something integrators should decide.

Q: What if IDFA cannot be obtained?

A: iOS 14+ requires ATT user authorization. Please confirm:

  • Info.plist has NSUserTrackingUsageDescription configured
  • UjuPrivacyConfig.canUseIDFA is set to true
  • User has authorized ATTrackingManager.AuthorizationStatus.authorized
  • When unauthorized, the SDK still works (uses IDFV as fallback), but attribution accuracy decreases

Best Practices

  1. Initialize early: Complete two-phase initialization in didFinishLaunchingWithOptions
  2. Strict two-phase order: Must call initialize first, then start
  3. Handle failures: Implement onInitFailed to ensure the app still runs normally when initialization fails
  4. Debug mode: Set isDebug = true during development, change to false before release
  5. Privacy compliance: UjuPrivacyConfig defaults to all false; explicitly enable authorization fields as needed
  6. Resource release: Call destroy() when the app exits

Next Steps

After completing SDK initialization, you can start integrating specific ad types: