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

SwiftUI插页广告导致返回UITextField时视图消失问题

解决插页广告关闭后UITextField键盘上推视图异常问题

问题现象

点击UITextField时键盘弹出正常,但展示插页广告并关闭后,再次点击UITextField,键盘会过度上推所有视图,导致部分视图从屏幕中消失。

解决方案

方案1:广告关闭后强制刷新布局

在广告关闭回调中触发SwiftUI视图布局刷新,恢复正确的键盘适配逻辑:

  1. 修改AdsViewModel,添加用于触发布局刷新的状态:
class AdsViewModel: ObservableObject {
    static let shared = AdsViewModel()
    @Published var interstitial = AdsManager.Interstitial()
    @Published var showInterstitial = false {
        didSet {
            if showInterstitial {
                interstitial.showAd()
                showInterstitial = false
            } else {
                interstitial.requestInterstitialAds()
            }
        }
    }
    // 新增:触发视图布局刷新的状态
    @Published var shouldRefreshLayout = false
}
  1. 在AdsManager.Interstitial的广告关闭方法中更新状态:
func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
    // 通知ViewModel触发布局刷新
    AdsViewModel.shared.shouldRefreshLayout.toggle()
}
  1. 在主视图中监听状态变化,强制刷新布局:
struct ContentView: View {
    @EnvironmentObject var adsViewModel: AdsViewModel
    
    var body: some View {
        // 你的原有视图结构
        VStack {
            // ... 视图元素
            TextField("输入内容", text: .constant(""))
        }
        .onChange(of: adsViewModel.shouldRefreshLayout) { _ in
            // 强制根视图重新计算布局
            UIApplication.shared.windows.first?.rootViewController?.view.layoutIfNeeded()
        }
        .simultaneousGesture(TapGesture().onEnded{ adsViewModel.showInterstitial = true })
    }
}

方案2:修正广告展示的视图控制器获取逻辑

避免直接使用窗口根视图控制器,改为获取当前最顶层的活跃视图控制器,减少对SwiftUI布局的干扰:

修改AdsManager.Interstitial中的showAd方法:

func showAd() {
    guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
          let rootVC = windowScene.windows.first?.rootViewController else {
        print("无法获取根视图控制器")
        return
    }
    // 遍历获取当前最顶层的视图控制器
    var topVC = rootVC
    while let presentedVC = topVC.presentedViewController {
        topVC = presentedVC
    }
    
    if let fullScreenAds = interstitial {
        fullScreenAds.present(fromRootViewController: topVC)
    } else {
        print("广告尚未准备完毕")
    }
}

方案3:手动处理键盘偏移,禁用系统自动调整

使用ScrollView包裹内容,通过监听键盘高度变化手动控制视图偏移,替代系统的自动键盘适配:

  1. 创建键盘监听工具类:
class KeyboardObserver: ObservableObject {
    @Published var keyboardHeight: CGFloat = 0
    
    init() {
        let center = NotificationCenter.default
        center.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
        center.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    @objc private func keyboardWillShow(_ notification: Notification) {
        guard let frame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
        keyboardHeight = frame.height
    }
    
    @objc private func keyboardWillHide(_ notification: Notification) {
        keyboardHeight = 0
    }
}
  1. 在主视图中应用手动键盘偏移:
struct ContentView: View {
    @EnvironmentObject var adsViewModel: AdsViewModel
    @StateObject private var keyboardObserver = KeyboardObserver()
    
    var body: some View {
        ScrollView {
            // 你的所有视图内容
            VStack(spacing: 16) {
                // ... 各类视图元素
                TextField("输入内容", text: .constant(""))
                    .textFieldStyle(.roundedBorder)
            }
            .padding()
        }
        .padding(.bottom, keyboardObserver.keyboardHeight)
        .animation(.easeInOut, value: keyboardObserver.keyboardHeight)
        .simultaneousGesture(TapGesture().onEnded{ adsViewModel.showInterstitial = true })
    }
}

说明

以上方案可单独使用,也可组合应用,根据实际场景选择最合适的方式解决键盘上推异常问题。

内容的提问来源于stack exchange,提问作者Mohammed D Mirzada

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 19:24:57