Search code examples
iosswiftadmobinterstitial

Frustrating memory leak when loading an interstitial ad in Swift


I am dealing with an infuriating memory leak in regards to loading an interstitial ad via AdMob. When observing the memory in Xcode & Instruments, the memory jumps 10 MB every time I visit the view controller hosting the ad. Also when closing the app on my phone and reopening it, causes the memory to jump 30-40 mb as well which is just ridiculous.

I have tried profiling this in Instruments and the memory being allocated are all system libraries and nothing that points out to what is wrong. I have read other Stack Overflow answers such as ADMOB Memory Leaking? but no answer has helped me so far. Maybe somebody can tell me what is wrong with my code? I have followed the exact documentation AdMob provides which is https://developers.google.com/admob/ios/interstitial and all works fine except this crazy memory leak. Here is the exact code that is causing the leak below.


class ViewController: UIViewController, GADInterstitialDelegate {

var interstitial: GADInterstitial!

override func viewDidLoad() {
  interstitial = createAndLoadInterstitial()
  interstitial.delegate = self
}

func update() {
        if interstitial.isReady {
            interstitial.present(fromRootViewController: self)
        }
    }

    func createAndLoadInterstitial() -> GADInterstitial {
        let interstitial = GADInterstitial(adUnitID: "ca-app-pub-3940256099942544/4411468910")
        interstitial.delegate = self
        let request = GADRequest()
        interstitial.load(request)
        return interstitial
    }

    func interstitialDidDismissScreen(_ ad: GADInterstitial) {
        interstitial = createAndLoadInterstitial()
    }

// I am calling update() inside a button when pressed in this VC.

Solution

  • I just want to say that this actually has been solved by me. I did as one of the above stated in the comments. I took my code that was on the view controller hosting the interstitial ad and moved it to the app delegate. I simply then just referenced the interstitial ad object whenever I need it in my project. This brought the memory back down to whatever it allocated upon visiting the controller hosting the ad. For those that want to see a very simple example of what this looks like in the app delegate:

    import UIKit
    import GoogleMobileAds
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate, GADInterstitialDelegate {
    
        var myInterstitial: GADInterstitial!
    
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
            GADMobileAds.sharedInstance().start(completionHandler: nil)
            myInterstitial = createAndLoadInterstitial()
            return true
        }
    
        func createAndLoadInterstitial() -> GADInterstitial {
            let interstitial = GADInterstitial(adUnitID: "yourAdID")
            interstitial.delegate = self
            let request = GADRequest()
            interstitial.load(request)
            return interstitial
        }
    
        func interstitialDidDismissScreen(_ ad: GADInterstitial) {
            myInterstitial = createAndLoadInterstitial()
        }