Reputation: 555
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)
}
}
}
Upvotes: 6
Views: 2854
Reputation: 1144
Important! Simply: When creating a root view, you need to select the LAST view from the hierarchy, then the advertisement will be shown from any view (for example, a sheet)
let root = UIApplication.shared.windows.last?.rootViewController
func showAd () {
if let interstitial = interstitialAd {
let root = UIApplication.shared.windows.last?.rootViewController
interstitial.present(fromRootViewController: root!)
}
}
Upvotes: 0
Reputation: 1835
You can take a very basic approach. Just create a class which makes a new request every time you call its load method, as soon as ad is loaded it should inform your view, and whenever you want to display your ad just call its show method as shown below:-
import Foundation
import GoogleMobileAds
import UIKit
final class InterstitialAd : NSObject, GADInterstitialDelegate, ObservableObject {
var interstitialAd: GADInterstitial? = nil
@Published var isLoaded: Bool = false
func LoadInterstitial() {
interstitialAd = GADInterstitial(adUnitID: Constants.interstitialAdCode)
let req = GADRequest()
interstitialAd!.load(req)
interstitialAd!.delegate = self
}
func showAd() {
if let interstitialAd = self.interstitialAd, interstitialAd.isReady {
let root = UIApplication.shared.windows.first?.rootViewController
interstitialAd.present(fromRootViewController: root!)
isLoaded = false
}
}
func interstitialWillLeaveApplication(_ ad: GADInterstitial) {
print("user clicked ad")
}
func interstitialDidReceiveAd(_ ad: GADInterstitial) {
print("ad loaded")
isLoaded = true
}
}
Upvotes: 0
Reputation: 475
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)
}
}
}
Upvotes: 4