问题
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