How do I use the Google Mobile Ads SDK in SwiftUI, or use the UIKit UIViewController within a SwiftUI view?

冷暖自知 提交于 2021-01-20 21:58:59

问题


I have a SwiftUI view that I want to open a rewarded ad from the Google Mobile Ads SDK when I press a button. The instructions for loading the ads (https://developers.google.com/admob/ios/rewarded-ads#create_rewarded_ad) are in UIKit, and I'm struggling to use them in my SwiftUI app. Is there a way to load the ads using SwiftUI, or if I use UIKit, how do I integrate it into SwiftUI?

This is the SwiftUI parent view:

struct AdMenu: View {

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

I don't know UIKit, but I think this is the code I want to use in 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()
}

回答1:


I have used a very simple approach. I have a delegate class which loads the rewarded Ad and informs the view that its loaded, hence the view presents it. When user watches the full Ad, same delegate gets the success callback and it informs the view about it.

The code for delegate looks like:-

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) {}
}

Now you need a view to initiate and present the 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()
    }
}
}

Explanation:- In the above view when user taps on Load Ad, we initiate the loading and then the delegate updates the Published Boolean. This informs our view that ad is Loaded and we call:-

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

The Ad is now playing on screen and if user watches is completely, the delegate will get a success callback and it'll update another Published Boolean. This will inform us that we need to reward the user now (you can add your way to handle/reward the user).

I hope this helps. Happy coding...



来源:https://stackoverflow.com/questions/62415556/how-do-i-use-the-google-mobile-ads-sdk-in-swiftui-or-use-the-uikit-uiviewcontro

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!