You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS端Google AdMob RewardedAd安全区适配问题求助

iPhone 上 Google AdMob RewardedAd 安全区失效导致关闭按钮无法点击的解决方法

问题描述

在iPhone设备上,Google AdMob RewardedAd偶尔会拉伸至屏幕边缘,忽略安全区域,导致关闭按钮与控制中心触发区域重叠,无法被点击。已尝试修改展示广告所用的currentUiViewController的安全区行为(忽略/遵循两种模式),但问题仍存在。

当前展示广告的核心代码片段:

extension UIApplication {
    
    var keyWindow: UIWindow? {
        connectedScenes
            .compactMap {
                $0 as? UIWindowScene
            }
            .flatMap {
                $0.windows
            }
            .first {
                $0.isKeyWindow
            }
    }
    
    public var rootViewController: UIViewController? {
        guard let keyWindow = UIApplication.shared.keyWindow, let rootViewController = keyWindow.rootViewController else {
            return nil
        }
        return rootViewController
    }
    
    public func topViewController(controller: UIViewController? = UIApplication.shared.rootViewController) -> UIViewController? {
        
        if controller == nil {
            return topViewController(controller: rootViewController)
        }
        
        if let navigationController = controller as? UINavigationController {
            return topViewController(controller: navigationController.visibleViewController)
        }
        
        if let tabController = controller as? UITabBarController {
            if let selectedViewController = tabController.selectedViewController {
                return topViewController(controller: selectedViewController)
            }
        }
        
        if let presentedViewController = controller?.presentedViewController {
            return topViewController(controller: presentedViewController)
        }
        
        return controller
    }
}

guard let currentUiViewController = UIApplication.shared.topViewController() else { return }
rewardedAd.present(fromRootViewController: currentUiViewController) {
     let reward = rewardedAd.adReward
     self.rewardAdPlaybackCallbacks?.onUserEarnedReward(rewardAdHandle: self.currentRewardAdHandle!)
}

可行的解决思路

1. 使用自定义容器ViewController承载广告

创建一个专门的容器VC,强制其遵循安全区规则,再将广告展示在这个容器上,避免直接使用顶层VC带来的适配问题:

class AdContainerViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .black
        
        if #available(iOS 11.0, *) {
            // 强制开启安全区布局
            view.insetsLayoutMarginsFromSafeArea = true
            view.layoutMargins = UIEdgeInsets(
                top: view.safeAreaInsets.top,
                left: 0,
                bottom: view.safeAreaInsets.bottom,
                right: 0
            )
        }
    }
    
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }
}

// 展示广告时替换原有逻辑
guard let topVC = UIApplication.shared.topViewController() else { return }
let adContainerVC = AdContainerViewController()
topVC.present(adContainerVC, animated: false) {
    self.rewardedAd.present(fromRootViewController: adContainerVC) {
        let reward = self.rewardedAd.adReward
        self.rewardAdPlaybackCallbacks?.onUserEarnedReward(rewardAdHandle: self.currentRewardAdHandle!)
        // 广告结束后关闭容器VC
        adContainerVC.dismiss(animated: false)
    }
}

2. 检查AdMob SDK版本与广告单元配置

  • 确保使用最新版本的Google Mobile Ads SDK,旧版本可能存在安全区适配的已知Bug;
  • 登录AdMob后台,检查对应广告单元的设置,尝试关闭自适应广告相关选项,强制广告使用固定尺寸适配安全区。

3. 手动调整广告关闭按钮的布局约束

通过遍历广告视图层级,找到关闭按钮的容器视图,手动添加安全区偏移约束(注意:此方法依赖AdMob SDK的视图结构,可能随版本变化失效):

// 广告展示后延迟执行,确保视图已加载完成
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
    guard let adRootView = self.rewardedAd.rootViewController?.view else { return }
    
    // 递归查找可能的关闭按钮容器(需根据实际视图结构调整判断条件)
    func findCloseButtonContainer(in view: UIView) -> UIView? {
        if view.frame.minY < view.safeAreaInsets.top {
            return view
        }
        for subview in view.subviews {
            if let container = findCloseButtonContainer(in: subview) {
                return container
            }
        }
        return nil
    }
    
    if let container = findCloseButtonContainer(in: adRootView), #available(iOS 11.0, *) {
        container.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            container.topAnchor.constraint(equalTo: adRootView.safeAreaLayoutGuide.topAnchor),
            container.trailingAnchor.constraint(equalTo: adRootView.trailingAnchor, constant: -16)
        ])
    }
}

4. 临时禁用控制中心触发(不推荐)

如果以上方案都无法快速生效,可临时在广告展示期间禁用控制中心下拉手势,但此方法会影响用户体验,仅作为应急方案:

// 展示广告前禁用交互(仅针对全屏广告场景)
UIApplication.shared.windows.first?.isUserInteractionEnabled = false

guard let currentUiViewController = UIApplication.shared.topViewController() else { 
    UIApplication.shared.windows.first?.isUserInteractionEnabled = true
    return 
}

rewardedAd.present(fromRootViewController: currentUiViewController) {
     let reward = self.rewardedAd.adReward
     self.rewardAdPlaybackCallbacks?.onUserEarnedReward(rewardAdHandle: self.currentRewardAdHandle!)
     // 广告结束后恢复交互
     UIApplication.shared.windows.first?.isUserInteractionEnabled = true
}

内容的提问来源于stack exchange,提问作者rdsarna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 04:10:05