如何在SpriteKit的SKScene中展示插屏广告?类型转换错误求解
Hey there! Let's fix that interstitial ad issue in SpriteKit right away.
The Root Cause of Your Error
The error Cannot convert value of type 'Start' to expected argument type 'UIViewController' happens because Google Mobile Ads' GADInterstitial.present(fromRootViewController:) method requires a UIViewController instance to display the ad—but your Start class is an SKScene, not a view controller. SpriteKit scenes run inside a view controller (usually a GameViewController), so we just need to get a reference to that parent view controller.
Step-by-Step Solution & Code Example
Here's how to properly implement interstitial ads in your SKScene:
- Add a reference to the parent view controller in your scene class
- Initialize and load the ad when the scene loads
- Present the ad using the view controller reference when needed
import SpriteKit import GoogleMobileAds class Start: SKScene, GADInterstitialDelegate { var interstitial: GADInterstitial! // Weak reference to avoid retain cycles weak var parentViewController: UIViewController? override func didMove(to view: SKView) { // Option 1: Get the root view controller from the scene's SKView parentViewController = view.window?.rootViewController // Option 2 (more reliable): If you have a custom GameViewController, pass it directly // (Add this to your GameViewController's viewDidLoad when presenting the scene) // scene.parentViewController = self // Initialize and load the interstitial ad interstitial = GADInterstitial(adUnitID: "YOUR_AD_UNIT_ID") interstitial.delegate = self interstitial.load(GADRequest()) } // Call this method when you want to show the ad (e.g., on a button tap) func showInterstitialAd() { guard let vc = parentViewController, interstitial.isReady else { print("Ad not ready or view controller reference missing") return } interstitial.present(fromRootViewController: vc) } // Delegate method to reload the ad after it's dismissed func interstitialDidDismissScreen(_ ad: GADInterstitial) { // Reinitialize and load a new ad for next time interstitial = GADInterstitial(adUnitID: "YOUR_AD_UNIT_ID") interstitial.delegate = self interstitial.load(GADRequest()) } }
Key Notes
- Use a weak reference for the view controller to prevent memory leaks.
- Always check if the ad is ready (
interstitial.isReady) before trying to present it—this avoids crashes if the ad hasn't finished loading. - Reload the ad after dismissal so you have a fresh ad ready for the next trigger event.
If you're using a custom GameViewController, passing the reference directly (Option 2) is more reliable than relying on rootViewController (especially if your app uses navigation controllers or tab bars).
内容的提问来源于stack exchange,提问作者Jack23

