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

如何在SwiftUI中点击按钮传递TextField值到视图控制器加载Admob广告

问题根因
  1. updateUIViewController 方法逻辑错误:你在该方法内新创建了一个 AdsScreenViewController 实例,完全没有操作已经渲染到页面上的原有控制器实例,修改新实例的auID没有任何实际效果。
  2. 广告加载逻辑只执行一次:你当前的广告加载代码只写在 viewDidLoad 生命周期里,该方法仅在控制器第一次初始化加载视图时调用一次,后续auID变化不会重新触发加载。
  3. 按钮逻辑冗余:你写的按钮点击事件 self.auID = auID 是无意义的自赋值,并不会触发任何新的逻辑。
修复方案

第一步:修改AdsScreenViewController

将bannerView提升为全局属性,新增auID的didSet监听,ID变化时自动重新加载广告:

import UIKit
import Foundation
import GoogleMobileAds
import ToastViewSwift

public class AdsScreenViewController: UIViewController, GADBannerViewDelegate {
    // 将bannerView提升为类属性
    var bannerView: GADBannerView!
    // 加didSet监听,ID变化时自动重新加载广告
    var auID = "" {
        didSet {
            // 避免ID为空时加载
            guard !auID.isEmpty else { return }
            bannerView.adUnitID = auID
            bannerView.load(GADRequest())
        }
    }
    
    init (auID: String){
        self.auID = auID
        super.init(nibName: nil, bundle: nil)
    }
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    public override func viewDidLoad() {
        super.viewDidLoad()
        bannerView = GADBannerView(adSize: kGADAdSizeBanner)
        addBannerViewToView(bannerView)
        bannerView.rootViewController = self
        bannerView.delegate = self
        // 初始化时如果ID不为空就加载
        if !auID.isEmpty {
            bannerView.adUnitID = auID
            bannerView.load(GADRequest())
        }
    }
    func addBannerViewToView(_ bannerView: GADBannerView) {
        bannerView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(bannerView)
        view.addConstraints(
            [NSLayoutConstraint(item: bannerView,
                                attribute: .bottom,
                                relatedBy: .equal,
                                toItem: bottomLayoutGuide,
                                attribute: .top,
                                multiplier: 1,
                                constant: 0),
             NSLayoutConstraint(item: bannerView,
                                attribute: .centerX,
                                relatedBy: .equal,
                                toItem: view,
                                attribute: .centerX,
                                multiplier: 1,
                                constant: 0)
            ])
    }
    public func bannerViewDidReceiveAd(_ bannerView: GADBannerView) {
        print("bannerViewDidReceiveAd")
    }
    public func bannerView(_ bannerView: GADBannerView, didFailToReceiveAdWithError error: Error) {
        print("bannerView:didFailToReceiveAdWithError: \(error.localizedDescription)")
    }
    public func bannerViewDidRecordImpression(_ bannerView: GADBannerView) {
        print("bannerViewDidRecordImpression")
    }
    public func bannerViewWillPresentScreen(_ bannerView: GADBannerView) {
        print("bannerViewWillPresentScreen")
    }
    public func bannerViewWillDismissScreen(_ bannerView: GADBannerView) {
        print("bannerViewWillDIsmissScreen")
    }
    public func bannerViewDidDismissScreen(_ bannerView: GADBannerView) {
        print("bannerViewDidDismissScreen")
    }
}

第二步:修改BannerViewController的update逻辑

不要新建控制器实例,直接更新已有实例的auID:

struct BannerViewController: UIViewControllerRepresentable {
    var auID: String
    public typealias UIViewControllerType = AdsScreenViewController
    
    func makeUIViewController(context: Context) -> AdsScreenViewController {
        return AdsScreenViewController(auID: auID)
    }
    
    func updateUIViewController(_ uiViewController: AdsScreenViewController, context: Context) {
        // 直接更新已有控制器的auID,触发didSet里的加载逻辑
        uiViewController.auID = auID
    }
}

第三步:调整TestAdsView的逻辑

拆分输入ID和加载ID两个变量,避免输入过程中频繁触发加载:

import SwiftUI
import UIKit

struct TestAdsView: View {
    @State private var inputAuID = ""
    @State private var loadedAuID = ""
    
    var body: some View {
        List {
            VStack(alignment: .leading) {
                Text("AdUnit")
                    .font(.footnote).fontWeight(.medium)
                TextField("adunitid", text: $inputAuID)
                    .font(.headline)
            }
            VStack(alignment: .leading) {
                Button(action: {
                    // 点击按钮才把输入的ID赋值给要加载的ID
                    loadedAuID = inputAuID
                }) {
                    Text("Show Ad")
                }
                BannerViewController(auID: loadedAuID)
            }
        }
    }
}

struct TestAdsView_Previews: PreviewProvider {
    static var previews: some View {
        TestAdsView()
    }
}

修改完成后点击Show Ad按钮即可正常触发广告加载逻辑,如果需要输入过程中实时加载,直接把BannerViewController的auID绑定为inputAuID即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 23:45:06