skip to Main Content

I want to design a swiftui view MainView() where an interstitial ad will be presented without reloading MainView().

My strategy is:

  1. Load ad from GADInterstitialAd,
  2. Present the ad on a UIViewController(). Then make UIViewControllerRepresentable to be presentable in swiftui.
  3. Present it to the MainView() using fullScreenCover(isPresented: , content: ) modifier.

But every time while the ad presented, the MainView() goes to .onDisappear state, and after closing the ad, it goes to .onAppear state. For that reason the MainView() is fully reloaded. I want to stop this reloading issue. How should I actually present the ad in my view?

Update: Here I have added AdView for more clarification.

struct nterstitialAdView: UIViewControllerRepresentable {
    var interstitialAd: GADInterstitialAd?
    var callback: () -> Void

    func makeUIViewController(context: Context) -> UIViewController {
        let view = UIViewController()
        DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1)) {
            self.showAd(from: view, callback: callback)
        }
        return view
    }

    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
    
    }

    func showAd(from root: UIViewController, callback: () -> Void) {
        if let ad = interstitialAd {
            ad.present(fromRootViewController: root)
            callback()
            print(":: Ad Presented")
        } else {
            print(":: Ad not ready")
            callback()
        }
    }
}

2

Answers


  1. Rather than present using fullScreenCover, how about displaying the ViewController in a ZStack, for example:

    struct ContentView: View {
        
        @State private var showAd = false
        
        var body: some View {
            ZStack {
                VStack {
                    Text("Main View")
                }
                .task {
                    //  Show AdView after a delay
                    try? await Task.sleep(nanoseconds: 2_000_000_000)
                    showAd = true
                }
                .onAppear {
                    print("Appearing") // This is only called once
                }
                
                if showAd {
                    AdView {
                        showAd = false
                    }
                    .edgesIgnoringSafeArea(.all)
                }
            }
        }
    }
    
    // Just an example view for testing
    struct AdView: UIViewControllerRepresentable {
        
        let dismiss: () -> Void
        
        func makeUIViewController(context: Context) -> UIViewController {
            let vc = UIViewController()
            vc.view.backgroundColor = .red
            let button = UIButton(type: .custom, primaryAction: UIAction(handler: { _ in
                dismiss()
            }))
            button.setTitle("Dismiss", for: .normal)
            button.translatesAutoresizingMaskIntoConstraints = false
            vc.view.addSubview(button)
            vc.view.centerXAnchor.constraint(equalTo: button.centerXAnchor).isActive = true
            vc.view.centerYAnchor.constraint(equalTo: button.centerYAnchor).isActive = true
            return vc
        }
        
        func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
        }
    }
    

    It should be pretty straightforward to animate the AdView in, if that’s what’s required.

    Login or Signup to reply.
  2. You can track in a Bool whether your page has already loaded and not reload it if it did.

    Other than that The iOS is made to execute OnAppear in that case, that happens both in UIKit and SwiftUI, so even calling UIKit in help won’t work.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search