First Look
让 CloudX 优先填充广告位,然后回退到您现有的聚合设置
First Look 让 CloudX 优先获得广告位填充机会,同时保留您现有的聚合设置作为回退路径。建议先从一个广告位开始,验证加载和展示行为后,再扩展到更多广告位。
此示例使用 AdMob 插屏广告作为回退。相同模式也适用于其他回退聚合平台:先加载 CloudX;只有当 CloudX 未加载成功时才加载回退广告;当两个来源都未准备好时,让应用流程继续。
FirstLookInterstitialController.swift
import CloudXCore
import GoogleMobileAds
import UIKit
@MainActor
final class FirstLookInterstitialController: NSObject {
enum Source {
case cloudX
case adMob
}
protocol Listener: AnyObject {
func firstLookInterstitialController(_ controller: FirstLookInterstitialController, didLoad source: Source)
func firstLookInterstitialController(_ controller: FirstLookInterstitialController, didFailToLoad source: Source, message: String?)
func firstLookInterstitialController(_ controller: FirstLookInterstitialController, didShow source: Source)
func firstLookInterstitialController(_ controller: FirstLookInterstitialController, didFailToShow source: Source, message: String?)
func firstLookInterstitialController(_ controller: FirstLookInterstitialController, didClose source: Source)
func firstLookInterstitialController(_ controller: FirstLookInterstitialController, didClick source: Source)
}
weak var listener: Listener?
private weak var viewController: UIViewController?
private let cloudXInterstitial: CLXInterstitial
private let adMobAdUnitId: String
private var adMobInterstitial: InterstitialAd?
private var isLoadingCloudX = false
private var isLoadingAdMob = false
init?(
viewController: UIViewController,
cloudXAdUnitId: String,
adMobAdUnitId: String
) {
guard let cloudXInterstitial = CloudXCore.shared.createInterstitial(adUnitId: cloudXAdUnitId) else {
return nil
}
self.viewController = viewController
self.cloudXInterstitial = cloudXInterstitial
self.adMobAdUnitId = adMobAdUnitId
super.init()
self.cloudXInterstitial.delegate = self
}
func load() {
guard !isLoadingCloudX,
!isLoadingAdMob,
!cloudXInterstitial.isReady,
adMobInterstitial == nil else {
return
}
isLoadingCloudX = true
cloudXInterstitial.load()
}
func show() -> Bool {
guard let viewController else {
return false
}
if cloudXInterstitial.isReady {
cloudXInterstitial.show(from: viewController)
return true
}
return showAdMobFallback(from: viewController)
}
func destroy() {
cloudXInterstitial.destroy()
adMobInterstitial = nil
listener = nil
}
private func loadAdMobFallback() {
guard !isLoadingAdMob, adMobInterstitial == nil else {
return
}
isLoadingAdMob = true
InterstitialAd.load(with: adMobAdUnitId, request: Request()) { [weak self] ad, error in
guard let self else { return }
self.isLoadingAdMob = false
if let error {
self.adMobInterstitial = nil
self.listener?.firstLookInterstitialController(self, didFailToLoad: .adMob, message: error.localizedDescription)
return
}
guard let ad else {
self.adMobInterstitial = nil
self.listener?.firstLookInterstitialController(self, didFailToLoad: .adMob, message: nil)
return
}
ad.fullScreenContentDelegate = self
self.adMobInterstitial = ad
self.listener?.firstLookInterstitialController(self, didLoad: .adMob)
}
}
private func showAdMobFallback(from viewController: UIViewController) -> Bool {
guard let adMobInterstitial else {
return false
}
adMobInterstitial.present(from: viewController)
return true
}
}
extension FirstLookInterstitialController: CLXInterstitialDelegate {
func didLoad(_ ad: CLXAd) {
isLoadingCloudX = false
listener?.firstLookInterstitialController(self, didLoad: .cloudX)
}
func didFailToLoadAd(_ adUnitId: String, error: CLXError) {
isLoadingCloudX = false
loadAdMobFallback()
}
func didDisplay(_ ad: CLXAd) {
listener?.firstLookInterstitialController(self, didShow: .cloudX)
}
func didFailToDisplay(_ ad: CLXAd, error: CLXError) {
if let viewController, showAdMobFallback(from: viewController) {
return
}
listener?.firstLookInterstitialController(self, didFailToShow: .cloudX, message: error.localizedDescription)
}
func didHide(_ ad: CLXAd) {
listener?.firstLookInterstitialController(self, didClose: .cloudX)
}
func didClick(_ ad: CLXAd) {
listener?.firstLookInterstitialController(self, didClick: .cloudX)
}
}
extension FirstLookInterstitialController: FullScreenContentDelegate {
func adWillPresentFullScreenContent(_ ad: FullScreenPresentingAd) {
adMobInterstitial = nil
listener?.firstLookInterstitialController(self, didShow: .adMob)
}
func adDidDismissFullScreenContent(_ ad: FullScreenPresentingAd) {
adMobInterstitial = nil
listener?.firstLookInterstitialController(self, didClose: .adMob)
}
func ad(_ ad: FullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
adMobInterstitial = nil
listener?.firstLookInterstitialController(self, didFailToShow: .adMob, message: error.localizedDescription)
}
func adDidRecordClick(_ ad: FullScreenPresentingAd) {
listener?.firstLookInterstitialController(self, didClick: .adMob)
}
}在广告位触发时调用 show()。如果返回 false,表示 CloudX 和回退广告都没有准备好,此时应继续应用流程,不展示广告。
if firstLookInterstitial?.show() != true {
continueToNextScreen()
}广告展示、关闭或最终失败后,请在您的应用准备好下一次广告位机会时再次调用 load()。