如何在SwiftUI中点击按钮传递TextField值到视图控制器加载Admob广告
问题根因
updateUIViewController方法逻辑错误:你在该方法内新创建了一个AdsScreenViewController实例,完全没有操作已经渲染到页面上的原有控制器实例,修改新实例的auID没有任何实际效果。- 广告加载逻辑只执行一次:你当前的广告加载代码只写在
viewDidLoad生命周期里,该方法仅在控制器第一次初始化加载视图时调用一次,后续auID变化不会重新触发加载。 - 按钮逻辑冗余:你写的按钮点击事件
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
相关产品推荐
相关产品推荐

