I'm using the latest implementation of admob with SwiftUI. Everything is working as expected. But I'd like to dismiss the parent view when an ad has completed, or when it's dismissed. I'm very new to delegates and can't quite wrap my head around how they work.
My SomeView is a horizontal tab view in a navigation stack, and I can dismiss it with presentationMode.wrappedValue.dismiss()
What I'd like is the adCoordinator's adDidDismissFullScreenContent
method to dismiss SomeView when the user dismissed the ad, it prints just fine.
I've tried adding an adDismissed
binding variable, and I've tried to hook my viewModel into the adCoordinator
. But couldn't quite get either to work.
Any help would be much appreciated, thanks!
import SwiftUI
import CoreData
struct SomeView: View {
@ObservedObject var viewModel: ViewModel
private let adViewControllerRepresentable = AdViewControllerRepresentable()
private let adCoordinator = AdCoordinator()
@Binding var adDismissed: Bool
var body: some View {
VStack(alignment: .center) {
Button("save_btn") {
adCoordinator.presentAd(from: adViewControllerRepresentable.viewController)
}.background {
// Add the adViewControllerRepresentable to the background so it
// doesn't influence the placement of other views in the view hierarchy.
adViewControllerRepresentable
.frame(width: .zero, height: .zero)
}.onAppear{
print("On Appear")
adCoordinator.loadAd()
}
}
}
}
import Foundation
import SwiftUI
import GoogleMobileAds
class AdCoordinator: NSObject, GADFullScreenContentDelegate {
private var ad: GADInterstitialAd?
func loadAd() {
GADInterstitialAd.load(
withAdUnitID: "ca-app-pub-3940256099942544/4411468910", request: GADRequest()
) { ad, error in
if let error = error {
return print("Failed to load ad with error: \(error.localizedDescription)")
}
print("ad loading")
self.ad = ad
self.ad?.fullScreenContentDelegate = self
}
}
// MARK: - GADFullScreenContentDelegate methods
func adDidRecordImpression(_ ad: GADFullScreenPresentingAd) {
print("\(#function) called")
}
func adDidRecordClick(_ ad: GADFullScreenPresentingAd) {
print("\(#function) called")
}
func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
print("\(#function) called")
}
func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
print("\(#function) called")
}
func adWillDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
return print("\(#function) called")
}
func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
print("\(#function) called")
}
func presentAd(from viewController: UIViewController) {
guard let fullScreenAd = ad else {
return print("Ad wasn't ready")
}
fullScreenAd.present(fromRootViewController: viewController)
}
}
struct AdViewControllerRepresentable: UIViewControllerRepresentable {
let viewController = UIViewController()
func makeUIViewController(context: Context) -> some UIViewController {
return viewController
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
// No implementation needed. Nothing to update.
}
}
I've found a way to make this work, in case anyone else has the same issue. I'm not sure if it's the best way, but I used observable objects and a published bool eg.
private class InterstitialAdCoordinator: NSObject, GADFullScreenContentDelegate, ObservableObject {
private var interstitial: GADInterstitialAd?
@Published var adWasDismissed = false
func loadAd() {
GADInterstitialAd.load(
withAdUnitID: "ca-app-pub-3940256099942544/4411468910", request: GADRequest()
) { ad, error in
self.interstitial = ad
self.interstitial?.fullScreenContentDelegate = self
}
}
func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
interstitial = nil
adWasDismissed = true
print("Ad dismissed \(adWasDismissed)")
}
func showAd(from viewController: UIViewController, completion: () -> Void, onFailure: () -> Void) {
if let interstitial = interstitial {
interstitial.present(fromRootViewController: viewController)
completion()
}
else {
onFailure()
return print("Ad wasn't ready")
}
}
}
I also added a completion handler, to the show ad func, in case the ad fails to display.