Apps Kit SDK logoApps Kit SDK
Docs · iOS Integration

4. Initializing the SDK

4.1 AppDelegate

Subclass AKSBaseAppDelegate — a template-method base class that does Firebase setup, AdMob init, SDK init, and remote-config bootstrapping for you, with a handful of open hooks for your app to plug into.

swift
import UIKit
import AppsKit
import AKSKit

class AppDelegate: AKSBaseAppDelegate {

    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        AppsKitSDKAdsManagerIOS.instance.initialize(userHasGivenConsent: true, isCCPAConsent: true)

        // super.application(...) does, in order:
        //   FirebaseApp.configure() -> MobileAds.shared.start() -> setupAdBridge()
        //   -> AppsKitSDK init/setDevMode/setTestMode/saveDefaultConfigJson
        //   -> configureSDK() -> manageRemoteConfigs(...)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }

    /// Called by the base class during the sequence above. Optional — only needed if your
    /// app has its own ad-loading abstraction layer that needs to be wired up to AKS. If you
    /// call `AppsKitSDKAdsManagerIOS.instance` directly from your own Swift code (§5), leave
    /// this empty.
    override func setupAdBridge() {}

    override func isDevMode() -> Bool { return false } // wire to your own debug flag
    override func isTestMode() -> Bool { return false }

    override func defaultConfigJson() -> String? {
        return "<encrypted-config-json-from-aks-portal>"
    }

    /// Called after dev/test mode flags are applied — use this for anything that needs
    /// to happen after the base setup but before remote config is ready (e.g. initializing
    /// AppLovin MAX directly).
    override func configureSDK() {}

    override func onConfigsReadyToUse() {
        // optional — fires once Firebase Remote Config has been fetched/activated
    }
}

Full list of open hooks on AKSBaseAppDelegate: setupAdBridge(), isDevMode() -> Bool (default false), isTestMode() -> Bool (default false), defaultConfigJson() -> String? (default nil), timeToFetchRemoteConfigInSeconds() -> Int (default 3600), onConfigsReadyToUse(), configureSDK().

4.2 Initializing without extending AKSBaseAppDelegate

Subclassing AKSBaseAppDelegate isn't mandatory — it's a convenience wrapper. If your app already has its own UIApplicationDelegate you can't give up, call the same AppsKitSDK/AKSKit methods it calls internally, directly from your own application(_:didFinishLaunchingWithOptions:):

swift
import UIKit
import AppsKit   // for makeDefaultIOSAdHandler() — see below
import AKSKit
import FirebaseCore
import FirebaseRemoteConfig
import GoogleMobileAds

class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        FirebaseApp.configure()
        MobileAds.shared.start()

        // If your app has its own ad-loading abstraction layer to wire up to AKS, do it
        // around here — most apps don't need this; see §5 to call ad formats directly.

        let sdkInstance = AppsKitSDK.shared
        sdkInstance.setIOSAdHandler(iosAdHandler: makeDefaultIOSAdHandler())
        sdkInstance.initialize(
            context: PlatformContext(delegate: nil),
            application: PlatformApplication(application: UIApplication.shared)
        )

        sdkInstance.setDevMode(value: false) // wire to your own debug flag
        sdkInstance.setTestMode(value: false)
        sdkInstance.setTimeToFetchRemoteConfigInSeconds(intervalToFetchRemoteConfigInSeconds: 3600) // optional, defaults to 3600

        sdkInstance.saveDefaultConfigJson(encryptedJson: "<encrypted-config-json-from-aks-portal>")
        sdkInstance.manageRemoteConfigs(onRemoteConfigReady: RemoteConfigReadyBridge {
            // optional — your own hook into the fetched remote config
        })

        AdsManager.shared.setAppExitTime(appExitTime: 0)
        AKSUtils.shared.cleanCachedData()

        return true
    }
}

// manageRemoteConfigs(onRemoteConfigReady:) takes an OnRemoteConfigAvailable, not a closure —
// AKSBaseAppDelegate has a private adapter for this internally; outside it, write your own:
private class RemoteConfigReadyBridge: NSObject, OnRemoteConfigAvailable {
    private let onReady: () -> Void
    init(_ onReady: @escaping () -> Void) { self.onReady = onReady }
    func onRemoteConfigReadyToFetch(remoteConfig: RemoteConfig) {
        DispatchQueue.main.async { self.onReady() }
    }
}

setIOSAdHandler(iosAdHandler:) needs a concrete IOSPlatformAdHandler — the one AKSBaseAppDelegate uses internally (AdMob/IronSource/MAX mediation init, AppsFlyer/Adjust reporting) is an internal SDK type, so it's exposed for exactly this case as makeDefaultIOSAdHandler().

What you give up by not subclassing AKSBaseAppDelegate: the automatic "App Open ad at application level" flow (§4.6) — requestSplashAppOpenAd/disableAppOpenSplashCallback/showAppOpenAdIfAvailable are instance methods of AKSBaseAppDelegate itself, not exposed on the bare AppsKitSDK object, and the foreground/background tracking that drives them lives in AKSBaseAppDelegate's own applicationWillEnterForeground/applicationDidBecomeActive/applicationWillResignActive overrides. If you still want an App Open ad, call AppsKitSDKAdsManagerIOS.instance.loadAppOpen/showAppOpen yourself (§5, App Open) at whatever point in your own startup flow you want one.

4.3 SwiftUI App entry point

If your app uses the SwiftUI App protocol rather than a storyboard, bridge to your AppDelegate with @UIApplicationDelegateAdaptor — this is what actually causes application(_:didFinishLaunchingWithOptions:) to run:

swift
import SwiftUI

@main
struct YourApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

The whole init sequence in §4.1 runs synchronously inside didFinishLaunchingWithOptions, before WindowGroup renders — so the ad bridge and SDK are ready before any UI shows.

swift
AppsKitSDKAdsManagerIOS.instance.initialize(userHasGivenConsent: true, isCCPAConsent: true)

The reference integration hardcodes both flags to true — there's no UMP/CMP consent flow wired up anywhere in it. That's a gap, not a recommendation: if your app is subject to GDPR/CCPA, run your own consent flow (Google's UMP SDK is already a transitive dependency via Google-Mobile-Ads-SDK, §1.2 — you just need to call it) or a custom CMP, and pass the real user decision into this call instead of a hardcoded true. Pair this with the ATT prompt from §3.3 if you also need IDFA.

4.5 Remove Ads / IAP gating

swift
AppsKitSDK.shared.setRemoveAdsStatus(status: true)   // call after a successful purchase/restore
AppsKitSDK.shared.getRemoveAdsStatus()               // check current status

Every load/show call already checks this internally — gate nothing yourself. Note the Swift access pattern: these manager types all surface as a class with a static .shared accessor (AppsKitSDK.shared, AKSLogManager.shared, PreferencesManager.shared, etc.) — you'll see this pattern throughout the SDK.

4.6 App Open ads at the application level

AKSBaseAppDelegate automatically tracks foreground/background transitions (applicationWillEnterForeground/applicationDidBecomeActive/applicationWillResignActive) and will show an App Open ad on warm starts if your AKS portal config has isAppOpenAtApplicationLvl enabled. Three methods are available for your splash flow:

swift
// Call from your splash screen — requests and shows an app-open ad
(appDelegate as? AKSBaseAppDelegate)?.requestSplashAppOpenAd(callbacks: myCallbacks, waitTimeInSeconds: 5)

// Stop the splash screen's callback from firing again on subsequent app-open events
(appDelegate as? AKSBaseAppDelegate)?.disableAppOpenSplashCallback()

// Manually trigger "show if one's already loaded and ready" — used internally on resume
(appDelegate as? AKSBaseAppDelegate)?.showAppOpenAdIfAvailable()