Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google AdMob interstitial in SwiftUI

Tags:

I try to integrate Interstitial ad in swiftUI, I create the UIViewControllerRepresentable class and the UIViewController.

https://developers.google.com/admob/ios/interstitial#show_the_ad

But I don't know how to show the ad once the ad ready and loaded.

in Admob documentation i have

  if interstitial.isReady {
                    interstitial.present(fromRootViewController: viewController)
                } else {
                    print("Ad wasn't ready")
                }

but I don't know where put his code and how input the view in my swiftUI view

import SwiftUI
import UIKit
import GoogleMobileAds

final class GADInterstitialViewController: UIViewControllerRepresentable {
    public var interstitial: GADInterstitial!
    public func makeUIViewController(context: UIViewControllerRepresentableContext<GADInterstitialViewController>) -> UIViewController {
        let interstitial = GADInterstitial(adUnitID: "ca-app-pub-3940256099942544/4411468910")
        let viewController = UIViewController()
        let request = GADRequest()
        interstitial.load(request)

        return viewController
    }

    func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<GADInterstitialViewController>) {

    }



}


struct Transit: View {


    var body: some View {
        ZStack{
            GADInterstitialViewController()
                .frame(width: screen.width, height: screen.height, alignment: .center)
        }

    }

}
like image 703
Nicolas M Avatar asked Oct 17 '19 20:10

Nicolas M


1 Answers

The solution doesn't work for me when the interstitial is not in the root view. After searching around, finally I could make it work.

I use an EnvironmentObject to hold the Interstitial

Xcode 11.5, Swift 5

import Foundation
import GoogleMobileAds
class SharedValues:ObservableObject{
    
    @Published var interstitial = GADInterstitial(adUnitID: "ca-app-pub-3940256099942544/4411468910")
    @Published var popInterstitial = false

}

And then create a struct or viewcontroller class to hold the ViewController/View which is used to display the Interstitial specifically. The code looks much but most of them are boilerplate codes.

struct InterstitialVC:UIViewControllerRepresentable{

@EnvironmentObject var sharing:SharedValues

func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
    
    if sharing.popInterstitial{
        
        showAd(uiViewController)
    }
}




func makeUIViewController(context: Context) -> some UIViewController {
    let vc = UIViewController()
    vc.view.frame = UIScreen.main.bounds

    sharing.interstitial.delegate = context.coordinator
    return vc
}

Here we implement the GADInterstitialDelegate, the Coordinator thing looks exotic to me the first time I see it. But when you get your hand dirty and you will find it very straight forward and convenient. You need the Coordinator thing to communicate between the delegate/UIKit and SwiftUI.

sharing.interstitial.delegate = context.coordinator

Above is the code you set the coordinator as your GADInterstitialDelegate, it may work good even if you don't implement the delegate methods. But those methods help a lot when you research and debug how things work.

func makeCoordinator() -> Coordinator {
    Coordinator(self)
}

class Coordinator:NSObject,GADInterstitialDelegate{
    var parent:InterstitialVC
    
    init(_ parent: InterstitialVC) {
        self.parent = parent
    }
    func interstitialDidReceiveAd(_ ad: GADInterstitial) {
        //do your things
        parent.sharing.popInterstitial = true
    }
    
    func interstitialDidDismissScreen(_ ad: GADInterstitial) {
        //do your things
        let request = GADRequest()
        parent.sharing.interstitial.load(request)
    }
    
    func interstitialWillPresentScreen(_ ad: GADInterstitial) {
        //do your things
    }
    func interstitialDidFail(toPresentScreen ad: GADInterstitial) {
        //do your things
    }
}

Almost all boilerplate codes. Notice that the Coordinate class is inside the InterstitialVC struct. I use the delegate method to determine when to pop and pre-load the Ad again.

func showAd(_ controller:UIViewController){
    
    if sharing.interstitial.isReady{
        sharing.interstitial.present(fromRootViewController: controller)
        sharing.popInterstitial = false
    }else{
        print("Not Ready Yet")
    }
}

}

In the ContentView or other views, find a good place to put/hide the InterstitialVC() before it pops. Voila

struct ContentView: View {
    @State var showInterstitial = true
    @EnvironmentObject var sharing:SharedValues
    var body: some View {
        ZStack{
//            if showInterstitial{
//                InterstitialVC()
//                   .edgesIgnoringSafeArea(.all)
//            }
            NavigationView{
                List{
                    NavigationLink("Show Second View", destination: SecondView())
                }
            }
           
            
            
        }.onAppear{
            
            let request = GADRequest()
            self.sharing.interstitial.load(request)
        }
        

    }
}

import SwiftUI
import GoogleMobileAds

struct SecondView: View {
    @EnvironmentObject var sharing:SharedValues
    
    @State var showInterstitial = true
    var body: some View {
        ZStack{
            if showInterstitial{
                
                InterstitialVC()
            }
            
            Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
        }
        .background(Color.yellow)
        .onAppear{
           let request = GADRequest()
           parent.sharing.interstitial.load(request)
          }
        
    }
}
like image 154
William Tong Avatar answered Sep 18 '22 22:09

William Tong