5. 광고 형식별 호출
모든 호출에는 동일하게 AKS 포털에서 설정한 플레이스홀더 문자열을 전달합니다. AKS는 런타임에 이 문자열을 광고 네트워크와 장애 시 대체 네트워크 목록으로 매핑합니다.
5.1 브리징 패턴
AKS의 광고 콜백 타입(AdsCallback, BannerCallback, NativeCallback, RewardedAdCallbacks, AppOpenAdCallbacks)은 클로저가 아니라, 상속하여 override하는 클래스입니다. 일반적인 구현 패턴(AppsKitSDKAdsManagerIOS를 사용하는 코드 전반에서 사용)은 형식별로 작은 비공개 어댑터 클래스를 만들고 다음과 같이 구현하는 것입니다.
- AKS 콜백 타입을 상속하고
super.init()을 호출합니다. - 각 생명주기 이벤트를 자체 UI 레이어의 요구사항에 맞게 전달합니다.
- 배너, 네이티브, 보상형 광고에서는 어댑터 자체에서 로드→표시를 연결합니다. 즉, 어댑터에서 재정의한
onBannerLoaded()/onNativeLoaded()/onRewardedLoaded()가 해당show...호출을 실행하며, 표시 단계의 콜백으로도self를 재사용합니다.
private class BannerCallbackAdapter: BannerCallback {
private let onLoaded: () -> Void
private let onFailed: (String) -> Void
private weak var container: UIView?
private let placeholder: String
init(container: UIView, placeholder: String, onLoaded: @escaping () -> Void, onFailed: @escaping (String) -> Void) {
self.container = container
self.placeholder = placeholder
self.onLoaded = onLoaded
self.onFailed = onFailed
super.init()
}
override func onBannerLoaded() {
onLoaded()
guard let vc = UIApplication.topViewController(), let view = container else {
onFailed("No active view controller found")
return
}
AppsKitSDKAdsManagerIOS.instance.showBanner(from: vc, placeholder: placeholder, container: view, callback: self)
}
override func onBannerFailedToLoad() { onFailed("") }
override func onBannerClicked() {}
override func onBannerShown() {}
override func onBannerSizeChanged(bannerSizes: BannerSizes) {}
override func setBannerSize(width: Double, height: Double) {}
}UIApplication.topViewController()는 AppsKit.xcframework가 UIApplication의 확장으로 제공하는 메서드입니다. 키 윈도우의 루트 뷰 컨트롤러에서 시작해 프레젠트된 뷰 컨트롤러, 내비게이션 컨트롤러, 탭 컨트롤러를 따라 내려가며 실제 최상단 화면을 찾습니다. 뷰 컨트롤러가 필요한 호출을 해야 하지만 UIView만 있거나 UI 컨텍스트가 전혀 없는 경우에 사용합니다.
전면 광고
// Load only
AppsKitSDKAdsManagerIOS.instance.loadInterstitial(from: viewController, placeholder: placeholder, callback: adapter)
// Show a previously loaded interstitial
AppsKitSDKAdsManagerIOS.instance.showInterstitial(from: viewController, placeholder: placeholder, callback: adapter)adapter는 AdsCallback을 상속합니다.
private class InterstitialCallbackAdapter: AdsCallback {
private let onAdLoaded: () -> Void
private let onAdFailed: () -> Void
init(onAdLoaded: @escaping () -> Void, onAdFailed: @escaping () -> Void) {
self.onAdLoaded = onAdLoaded
self.onAdFailed = onAdFailed
super.init()
}
override func onLoaded() { onAdLoaded() }
override func onFailedToLoad() { onAdFailed() }
override func onAdShown() {}
override func onAdDismissed() {}
override func onAdFailedToShow() {}
}보상형 광고
// Separate load/show — chain load→show in your adapter's onRewardedLoaded(), same pattern as banner/native
AppsKitSDKAdsManagerIOS.instance.loadRewarded(from: viewController, placeholder: placeholder, callback: adapter)
AppsKitSDKAdsManagerIOS.instance.showRewarded(from: viewController, placeholder: placeholder, callback: adapter)adapter는 RewardedAdCallbacks를 상속하고 onRewardedLoaded()에서 바로 showRewarded를 호출하도록 연결합니다. 표시 단계의 콜백으로는 self를 재사용합니다.
private class RewardedAdCallbackAdapter: RewardedAdCallbacks {
private let placeholder: String
private let onUserEarnedReward: () -> Void
private let onFailed: (String) -> Void
init(placeholder: String, onUserEarnedReward: @escaping () -> Void, onFailed: @escaping (String) -> Void) {
self.placeholder = placeholder
self.onUserEarnedReward = onUserEarnedReward
self.onFailed = onFailed
super.init()
}
override func onRewardedLoaded() {
guard let vc = UIApplication.topViewController() else {
onFailed("No active view controller found")
return
}
AppsKitSDKAdsManagerIOS.instance.showRewarded(from: vc, placeholder: placeholder, callback: self)
}
override func onAdRewarded() { onUserEarnedReward() }
override func onRewardedCompleted() { onUserEarnedReward() }
override func onAdRewardedAdDismissed() {}
override func onRewardedAdLoadFailure() { onFailed("Failed to load rewarded ad") }
override func onRewardedFailedToShow() { onFailed("Failed to show rewarded ad") }
}AKS는
AppsKitSDKAdsManagerIOS에서 한 번의 호출로 로드와 표시를 처리하는loadAndShowRewarded(from:placeholder:callback:)도 제공합니다. 이 메서드는onRewardedAdSuccess()/onRewardedAdFailed()만 포함하는 프로토콜인RewardedLoadAndShowCallback을 받습니다. 추상 클래스가 아닌 프로토콜이므로super.init()은 필요하지 않습니다. 미리 로드하고 나중에 표시해야 한다면 위의loadRewarded/showRewarded를 각각 사용하고, 항상 로드 직후 표시한다면loadAndShowRewarded를 사용하세요.
앱 오프닝 광고
AppsKitSDKAdsManagerIOS.instance.loadAppOpen(placeholder: placeholder, callback: adapter)
AppsKitSDKAdsManagerIOS.instance.showAppOpen(from: viewController, placeholder: placeholder, callback: adapter)adapter는 AppOpenAdCallbacks를 상속합니다.
private class AppOpenCallbackAdapter: AppOpenAdCallbacks {
private let onAdLoaded: () -> Void
private let onAdFailed: () -> Void
init(onAdLoaded: @escaping () -> Void, onAdFailed: @escaping () -> Void) {
self.onAdLoaded = onAdLoaded
self.onAdFailed = onAdFailed
super.init()
}
override func onLoaded() { onAdLoaded() }
override func onFailedToLoad() { onAdFailed() }
override func onAdShown() {}
override func onDismiss() {}
override func onAdFailToShow() {}
}이 방식은 앱 오프닝 광고를 수동으로 처리하는 방식입니다. 원격 설정에 따라 AKS가 애플리케이션 수준에서 자동으로 처리하도록 하려면 대신
AKSBaseAppDelegate의 내장 흐름을 사용하세요(§4.6).
배너 광고
AppsKitSDKAdsManagerIOS.instance.loadBanner(from: viewController, placeholder: placeholder, callback: adapter)
AppsKitSDKAdsManagerIOS.instance.showBanner(from: viewController, placeholder: placeholder, container: bannerContainerView, callback: adapter)adapter는 BannerCallback을 상속합니다. onBannerLoaded()에서 바로 showBanner를 호출하도록 연결하는 전체 BannerCallbackAdapter 정의는 위의 §5.1을 참고하세요.
BannerSizes: BANNER (320×50), LARGE_BANNER (320×100), MEDIUM_RECTANGLE (300×250), FULL_BANNER (468×60).
네이티브 광고
AppsKitSDKAdsManagerIOS.instance.loadNative(from: viewController, placeholder: placeholder, isShowInScrollView: true, callback: adapter)
AppsKitSDKAdsManagerIOS.instance.showNative(
from: viewController, container: nativeContainerView, placeholder: placeholder,
res: nil, isShowInScrollView: true, callback: adapter
)adapter는 NativeCallback을 상속하고, BannerCallbackAdapter와 동일한 패턴으로 onNativeLoaded()에서 바로 showNative를 호출하도록 연결합니다.
private class NativeCallbackAdapter: NativeCallback {
private weak var container: UIView?
private let placeholder: String
private let onAdLoaded: () -> Void
private let onAdFailed: (String) -> Void
init(container: UIView, placeholder: String, onAdLoaded: @escaping () -> Void, onAdFailed: @escaping (String) -> Void) {
self.container = container
self.placeholder = placeholder
self.onAdLoaded = onAdLoaded
self.onAdFailed = onAdFailed
super.init()
}
override func onNativeLoaded() {
onAdLoaded()
guard let vc = UIApplication.topViewController(), let view = container else {
onAdFailed("No active view controller found")
return
}
AppsKitSDKAdsManagerIOS.instance.showNative(
from: vc, container: view, placeholder: placeholder,
res: nil, isShowInScrollView: true, callback: self
)
}
override func onNativeFailedToLoad() { onAdFailed("") }
override func onNativeClicked() {}
override func onNativeShown() {}
}기능 프로모션
기능 프로모션도 다른 형식과 마찬가지로 AppsKitSDKAdsManagerIOS를 통해 호출합니다.
// Optional — exclude features the user already has unlocked from being promoted
AppsKitSDKAdsManagerIOS.instance.setFeaturesAvailable(availableFeatures: ["premium_theme", "no_ads"])
AppsKitSDKAdsManagerIOS.instance.showFeaturePromotion(
from: viewController,
placeholder: placeholder,
callback: adapter
)adapter는 OnFeaturePromotionClicked를 준수합니다. 추상 클래스가 아닌 프로토콜이므로 super.init()은 필요하지 않습니다.
private class FeaturePromotionAdapter: NSObject, OnFeaturePromotionClicked {
private let onClicked: (String) -> Void
private let onFailed: (String) -> Void
init(onClicked: @escaping (String) -> Void, onFailed: @escaping (String) -> Void) {
self.onClicked = onClicked
self.onFailed = onFailed
}
func onFeaturePromotionClicked(targetScreen: String) { onClicked(targetScreen) }
func onFailToShowFeaturePromotion(errorMessage: String) { onFailed(errorMessage) }
}