swiftuiadmobadmob-rewardedvideoad

How to keep a Bool state after Google AdMob RewardAd has finished displaying?


I'm currently developing an application using SwiftUI.

I'm trying to use a google AdMob reward Ad.

I made codes to show reward Ads referring to this article.

I'm trying to show an alert after I finish watching a reward Ad fully using a Bool state from RewardedAdDelegate class but It doesn't work...

How could I solve this problem?


Here are the codes:

AdShow.swift

import SwiftUI

struct AdShow: View {
    
    @ObservedObject var adDelegate = RewardedAdDelegate()
    
    var body: some View {
        
        RewardedAd()
            .alert(isPresented: $adDelegate.adFullyWatched){
                Alert(title: Text("reward Ad finished"),
                      message: Text("reward Ad finished"),
                      dismissButton: .default(Text("OK")))
            }
    }
}

RewardedAd.swift

import SwiftUI
import GoogleMobileAds

struct RewardedAd: View {
    
@EnvironmentObject var appState: AppState
@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()
        }
    }
}

RewardedAdDelegate

import Foundation
import GoogleMobileAds


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
        print("Reward received with currency: \(reward.type), amount \(reward.amount).")
    }
    
    /// Tells the delegate that the rewarded ad was presented.
    func rewardedAdDidPresent(_ rewardedAd: GADRewardedAd) {
        self.adLoaded = false
        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) {
        print("Rewarded ad failed to present.")
    }
}

UPDATED

AdShow.swift

import SwiftUI

struct AdShow: View {
    
    @ObservedObject var adDelegate = RewardedAdDelegate()
    
    var body: some View {
        VStack{
            RewardedAd(adDelegate: self.adDelegate)
                
                .alert(isPresented: $adDelegate.adFullyWatched){
                    Alert(title: Text(""),
                          message: Text(""),
                          dismissButton: .default(Text("OK")))
                }
            // check adDelegate.adFullyWatched state -> after Ad finish this text shows
            if adDelegate.adFullyWatched{
                Text("Checked")
            }
        }
    }
}

RewardedAd.swift

import SwiftUI
import GoogleMobileAds

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

ReUPDATED

AdShow.swift

import SwiftUI

struct AdShow: View {
    
    @ObservedObject var adDelegate = RewardedAdDelegate()
    @State var isAlert = false
    
    var body: some View {
        VStack{
            
            Button(action: {
                                self.isAlert = true
            }){
                Text("alert")
                    .padding()
            }
            RewardedAd(adDelegate: self.adDelegate)
                
                .alert(isPresented: self.$isAlert){
                    Alert(title: Text(""),
                          message: Text(""),
                          dismissButton: .default(Text("OK")))
                }
            // check adDelegate.adFullyWatched state -> after Ad finish this text shows
            if adDelegate.adFullyWatched{
                Text("Checked")
            }
            
        }
        .onAppear(){
            if adDelegate.adFullyWatched{
                self.isAlert = true
            }
        }
    }
}

Xcode: Version 12.0.1

iOS: 13.0


Solution

  • You use different instances of delegate in your views, instead you have to inject delegate from first view into second one.

    struct AdShow: View {
        
        @ObservedObject var adDelegate = RewardedAdDelegate()
        
        var body: some View {
            
            RewardedAd(adDelegate: self.adDelegate)      // << here inject !!
    
    // ... other code
    

    and

    struct RewardedAd: View {
        
    @EnvironmentObject var appState: AppState
    @ObservedObject var adDelegate: RewardedAdDelegate     // << here declare !!
    
    // ... other code