SwiftUI插页广告导致返回UITextField时视图消失问题
解决插页广告关闭后UITextField键盘上推视图异常问题
问题现象
点击UITextField时键盘弹出正常,但展示插页广告并关闭后,再次点击UITextField,键盘会过度上推所有视图,导致部分视图从屏幕中消失。
解决方案
方案1:广告关闭后强制刷新布局
在广告关闭回调中触发SwiftUI视图布局刷新,恢复正确的键盘适配逻辑:
- 修改
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 }
- 在
AdsManager.Interstitial的广告关闭方法中更新状态:
func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) { // 通知ViewModel触发布局刷新 AdsViewModel.shared.shouldRefreshLayout.toggle() }
- 在主视图中监听状态变化,强制刷新布局:
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包裹内容,通过监听键盘高度变化手动控制视图偏移,替代系统的自动键盘适配:
- 创建键盘监听工具类:
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 } }
- 在主视图中应用手动键盘偏移:
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
相关产品推荐
相关产品推荐

