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.
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:):
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:
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.
4.4 Consent and ad initialization
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 viaGoogle-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 hardcodedtrue. Pair this with the ATT prompt from §3.3 if you also need IDFA.
4.5 Remove Ads / IAP gating
AppsKitSDK.shared.setRemoveAdsStatus(status: true) // call after a successful purchase/restore
AppsKitSDK.shared.getRemoveAdsStatus() // check current statusEvery 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:
// 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()