2

我有一个 SwiftUI 视图,我想在按下按钮时从 Google 移动广告 SDK 打开一个奖励广告。加载广告的说明 ( https://developers.google.com/admob/ios/rewarded-ads#create_rewarded_ad ) 在 UIKit 中,我很难在我的 SwiftUI 应用程序中使用它们。有没有办法使用 SwiftUI 加载广告,或者如果我使用 UIKit,我如何将它集成到 SwiftUI 中?

这是 SwiftUI 父视图:

struct AdMenu: View {

    var body: some View {
   NavigationView {
       NavigationLink(destination: Ads())
        {
            Text("Watch Ad")
        }
    }
}
}

我不知道 UIKit,但我认为这是我想在 SwiftUI 中使用的代码:

    class ViewController: UIViewController, GADRewardedAdDelegate {

    var rewardedAd: GADRewardedAd?

var adRequestInProgress = false

  @IBAction func doSomething(sender: UIButton) {
    if rewardedAd?.isReady == true {
       rewardedAd?.present(fromRootViewController: self, delegate:self)
    }else {
      let alert = UIAlertController(
        title: "Rewarded video not ready",
        message: "The rewarded video didn't finish loading or failed to load",
        preferredStyle: .alert)
      let alertAction = UIAlertAction(
        title: "OK",
        style: .cancel,
        handler: { [weak self] action in
            // redirect to AdMenu SwiftUI view somehow?
        })
      alert.addAction(alertAction)
      self.present(alert, animated: true, completion: nil)
    }
}

func createAndLoadRewardedAd() {
    rewardedAd = GADRewardedAd(adUnitID: "ca-app-pub-3940256099942544/1712485313")
    adRequestInProgress = true
    rewardedAd?.load(GADRequest()) { error in
      self.adRequestInProgress = false
      if let error = error {
        print("Loading failed: \(error)")
      } else {
        print("Loading Succeeded")
      }
    }
  return rewardedAd
}

// Tells the delegate that the user earned a reward
func rewardedAd(_ rewardedAd: GADRewardedAd, userDidEarn reward: GADAdReward) {
  print("Reward received with currency: \(reward.type), amount \(reward.amount).")
}
// Tells the delegate that the rewarded ad was presented
func rewardedAdDidPresent(_ rewardedAd: GADRewardedAd) {
  print("Rewarded ad presented.")
}
// Tells the delegate that the rewarded ad was dismissed
func rewardedAdDidDismiss(_ rewardedAd: GADRewardedAd) {
  print("Rewarded ad dismissed.")
}
// Tells the delegate that the rewarded ad failed to present
func rewardedAd(_ rewardedAd: GADRewardedAd, didFailToPresentWithError error: Error) {
    rewardedAd = createAndLoadRewardedAd()
    print("Rewarded ad failed to present.")
}

    override func viewDidLoad() {
        super.viewDidLoad()
    if !adRequestInProgress && !(rewardedAd?.isReady ?? false) {
    rewardedAd = createAndLoadRewardedAd()
}
4

2 回答 2

3

我使用了一种非常简单的方法。我有一个委托类,它加载奖励广告并通知视图它已加载,因此视图呈现它。当用户观看完整的广告时,相同的代理会收到成功回调并将其通知视图。

代表的代码如下所示:-

class RewardedAdDelegate: NSObject, GADRewardedAdDelegate, ObservableObject {
@Published var adLoaded: Bool = false
@Published var adFullyWatched: Bool = false

var rewardedAd: GADRewardedAd? = nil

func loadAd() {
    rewardedAd = GADRewardedAd(adUnitID: "ca-app-pub-3940256099942544/1712485313")
        rewardedAd!.load(GADRequest()) { error in
          if error != nil {
            self.adLoaded = false
          } else {
            self.adLoaded = true
          }
        }
}

/// Tells the delegate that the user earned a reward.
func rewardedAd(_ rewardedAd: GADRewardedAd, userDidEarn reward: GADAdReward) {
    adFullyWatched = true
}

/// Tells the delegate that the rewarded ad was presented.
func rewardedAdDidPresent(_ rewardedAd: GADRewardedAd) {
     self.adLoaded = false
}

/// Tells the delegate that the rewarded ad was dismissed.
func rewardedAdDidDismiss(_ rewardedAd: GADRewardedAd) {}

/// Tells the delegate that the rewarded ad failed to present.
func rewardedAd(_ rewardedAd: GADRewardedAd, didFailToPresentWithError error: Error) {}
}

现在您需要一个视图来启动和展示 RewardedAd:-

struct RewardedAd: View {
@ObservedObject var adDelegate = RewardedAdDelegate()

var body: some View {
    if adDelegate.adLoaded && !adDelegate.adFullyWatched {
        let root = UIApplication.shared.windows.first?.rootViewController
        self.adDelegate.rewardedAd!.present(fromRootViewController: root!, delegate: adDelegate)
    }
    
    return Text("Load ad").onTapGesture {
        self.adDelegate.loadAd()
    }
}
}

说明:- 在上面的视图中,当用户点击 时Load Ad,我们启动加载,然后委托更新 Published 布尔值。这通知我们认为广告已加载,我们调用:-

让 root = UIApplication.shared.windows.first?.rootViewController self.adDelegate.rewardedAd!.present(fromRootViewController: root!, delegate: adDelegate)

广告现在正在屏幕上播放,如果用户观看完毕,代理将收到一个成功回调并更新另一个 Published Boolean。这将通知我们现在需要奖励用户(您可以添加处理/奖励用户的方式)。

于 2020-06-25T11:53:36.830 回答
0

我想出了一种方法,如何将 AdMob 页面中的 Objective-c 代码很好地转换为您可以在 SwiftUI 中轻松使用的东西。


final class RewardedAd {
    private let rewardId = "ca-app-pub-3940256099942544/1712485313" // TODO: replace this with your own Ad ID
    
    var rewardedAd: GADRewardedAd?
    
    init() {
        load()
    }
    
    func load(){
        let request = GADRequest()
        // add extras here to the request, for example, for not presonalized Ads
        GADRewardedAd.load(withAdUnitID: rewardId, request: request, completionHandler: {rewardedAd, error in
            if error != nil {
                // loading the rewarded Ad failed :( 
                return
            }
            self.rewardedAd = rewardedAd
        })
    }
    
    func showAd(rewardFunction: @escaping () -> Void) -> Bool {
        guard let rewardedAd = rewardedAd else {
            return false
        }
        
        guard let root = UIApplication.shared.keyWindowPresentedController else {
            return false
        }
        rewardedAd.present(fromRootViewController: root, userDidEarnRewardHandler: rewardFunction)
        return true
    }
}

我还添加了一个扩展来让根视图更容易:

extension UIApplication {
    
    var keyWindow: UIWindow? {
        return UIApplication.shared.connectedScenes
            .filter { $0.activationState == .foregroundActive }
            .first(where: { $0 is UIWindowScene })
            .flatMap({ $0 as? UIWindowScene })?.windows
            .first(where: \.isKeyWindow)
    }
    
    var keyWindowPresentedController: UIViewController? {
        var viewController = self.keyWindow?.rootViewController
        
        if let presentedController = viewController as? UITabBarController {
            viewController = presentedController.selectedViewController
        }
        
        while let presentedController = viewController?.presentedViewController {
            if let presentedController = presentedController as? UITabBarController {
                viewController = presentedController.selectedViewController
            } else {
                viewController = presentedController
            }
        }
        return viewController
    }
}

如果你将它添加到你的项目中,你可以在你的 SwiftUI 代码中这样调用它:

var rewardAd: RewardedAd
        
    init(){
        self.rewardAd = RewardedAd()
        rewardAd.load()
    }
    
    var body: some View {
        Button(action: {
            self.rewardAd.showAd(rewardFunction: {
              // TODO: give the user a reward for watching
              self.collectedDiamonds += 1
            })
        }) {
            Text("Watch Ad - Earn ")
                .foregroundColor(.white)
                .padding()
        }
        .background(Capsule().fill(Color.blue))
    }
于 2021-10-08T10:58:17.757 回答