SwiftUI - Google AdMob interstitial not showing in onAppear

Viewed 1523

I am trying to show an interstitial ad from google AdMob on appearing, but It Does not show up and it says "not ready" in the console. I have checked out many other tutorials and stack overflow pages on it but haven't found the answer. Can anyone help me? Here is my code:

struct ContentView: View {
@State var interstitial: GADInterstitial!
var body: some View{
    Text("Some Text").onAppear(perform: {
        self.interstitial = GADInterstitial(adUnitID: "ca-app-pub-3940256099942544/4411468910")
        let req = GADRequest()
        self.interstitial.load(req)


                if self.interstitial.isReady{
                        let root = UIApplication.shared.windows.first?.rootViewController
                        self.interstitial.present(fromRootViewController: root!)
                    }else {
                    print("not ready")
                }



    })
}
}
2 Answers

As mentioned in the comments using interstitialDidReceiveAd callback for showing ad is highly discouraged by Google Admob. Instead you can notify your view that Ad is loaded and then your view should take the decision that is it the correct time to show Interstitial Ad or not. So just create a helper class with a load and show function as shown:-

import Foundation
import GoogleMobileAds
import UIKit
    
final class InterstitialAd : NSObject, GADInterstitialDelegate, ObservableObject {
    var interstitial: GADInterstitial? = nil
    @Published var isLoaded: Bool = false
    
    func LoadInterstitial() {
        interstitial = GADInterstitial(adUnitID: Constants.interstitialAdCode)
        let req = GADRequest()
        interstitial!.load(req)
        interstitial!.delegate = self
    }
    
    func showAd() {
        if let fullScreenAd = self.interstitial, fullScreenAd.isReady {
           let root = UIApplication.shared.windows.first?.rootViewController
           fullScreenAd.present(fromRootViewController: root!)
           isLoaded = false
        }
    }
    
    func interstitialDidReceiveAd(_ ad: GADInterstitial) {
        isLoaded = true
    }
}

Now just use this class in your view and every time you call the load method it creates a new request (required as per doc). You should now observe the isLoaded Boolean from your View and can trigger the Ad on screen (using showAd) only when its intended to and not as soon as its loaded because we need to consider that user could be in middle of something...

The GADInterstitial.load is asynchronous operation and don't wait till ad is loaded, so you have to use delegate if you want to show add immediately after load.

Here is a possible solution

class MyDInterstitialDelegate: NSObject, GADInterstitialDelegate {

    func interstitialDidReceiveAd(_ ad: GADInterstitial) {
        if ad.isReady{
            let root = UIApplication.shared.windows.first?.rootViewController
            ad.present(fromRootViewController: root!)
        } else {
            print("not ready")
        }
    }
}

struct ContentView: View {
    @State var interstitial: GADInterstitial!
    private var adDelegate = MyDInterstitialDelegate()
    var body: some View{
        Text("Some Text").onAppear(perform: {
            self.interstitial = GADInterstitial(adUnitID: "ca-app-pub-3940256099942544/4411468910")
            self.interstitial.delegate = self.adDelegate

            let req = GADRequest()
            self.interstitial.load(req)
        })
    }
}
Related