Swift Admob插页式错误

这是相当长的,但它可能是一个非常简单的修复。 大部分是代码,只是跳到底部,会有一个tl;博士

嘿,所以我跟着大约10个关于让Admob插页式广告在我的Swift Spritekit游戏中运行的教程。 除了我见过的所有教程都使用了一个button的IBAction。 目前我希望广告在菜单上偶尔popup一次。 (刚开始,我可能会稍后再改变它)。 这一切都完美的作品,但一旦我点击播放button(去一个不同的场景),然后返回到菜单场景。 (GameScene)插页式function不再发生。 没有错误,只是在应用程序完全closures并重新打开之前不会再发生。

这是代码。

在我的GameViewController类中,我有:

var interstital: GADInterstitial! 

并在GameViewController加载我有:

 if let scene = GameScene(fileNamed:"GameScene") { let skView = self.view as? SKView skView!.ignoresSiblingOrder = false scene.scaleMode = .AspectFill scene.viewController = self skView!.presentScene(scene) interstital = GADInterstitial(adUnitID: "ca-app-pub-9776687746813194/9687097060") let request = GADRequest() interstital.loadRequest(request) 

同样在GameViewController类中,我有这些function:

 func ShowAd() { print("doing the showadfunc now") if (interstital.isReady) { print("there is an inter ready") interstital.presentFromRootViewController(self) interstital = CreateAd() } else{ print("The interstitial wasn't ready.") } } func CreateAd() -> GADInterstitial { let interstital = GADInterstitial(adUnitID: "ca-app-pub-9776687748683194/9687247060") interstital.loadRequest(GADRequest()) return interstital } 

在我的GameScene(菜单)类中,我有:

 var viewController: GameViewController! 

而在我的GameScene的类中,我有这个function来显示插页式广告。

 func adThing(){ //viewController?.ShowAd() print("starting the ad function") let waitForInterstitial = SKAction.waitForDuration(15.0) let waitForInterstitialShort = SKAction.waitForDuration(3.0) let showInterstitialAd = SKAction.runBlock({self.viewController?.ShowAd(); print("the function has been called..")}) let waitThenShowInterstitial = SKAction.sequence([showInterstitialAd,waitForInterstitial]) let waitThenShowInterStitialForever = SKAction.repeatActionForever(waitThenShowInterstitial) //self.runAction(waitThenShowInterStitialForever) self.runAction(waitForInterstitialShort, completion: { print("its waited 3 seconds and will now start the ad thingo") self.runAction(waitThenShowInterStitialForever) }) print("done") } 

所以,我每20秒就会在GameScene中调用ShowAd函数(它位于gameviewcontroller中)( 我已经证实它至less认为它正在调用该函数)。当应用程序打开时,它完美地工作。 但是,当我改变场景,然后返回到菜单场景(GameScene),我的GameScene函数中的打印继续进行,我的代码认为它正在调用ShowAd函数,但似乎没有任何事情发生,没有插页式popup,甚至不在GameViewController中的ShowAd函数中。

所以在我改变场景并返回之后,我的游戏忘记了GameViewController是什么。 如果我没有'?'引用GameViewController 它会崩溃我的游戏与错误“意外地发现零,而解包可选”。 所以改变场景后,也许GameViewController成为零? 我怎样才能解决这个问题。

请帮帮我!!! (我不熟悉编程,以防万一你不知道,我知道对我的代码做一个讽刺的评论是非常诱人的,它实际上只是骨头,而不是那么好。

非常感谢你,如果你能帮助我,哇..感谢您阅读所有这些..;)

你最可能的问题是,一旦你转换到一个新的场景viewController属性设置为零,因此如果您使用!

一般来说,在你的SKScenes中引用viewController的最佳做法是使用Delegation或NSNotification Center。

1)通知中心(最简单的方法)

在您的ViewController中,您可以在其中显示广告function,在ViewDidLoad中添加一个NSNotificationCenter观察器

  NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(showAd), name: "ShowInterAdKey", object: nil) 

(select器是调用的函数,名称是引用这个观察者的关键)

当您想要显示广告时,只需在您的SKScenes上发布通知

  NSNotificationCenter.defaultCenter().postNotificationName("ShowInterAdKey", object: nil) 

2)代表例子查看这些文章。

http://stephenradford.me/creating-a-delegate-in-swift/

https://www.natashatherobot.com/ios-weak-delegates-swift/

3)我还注意到,在展示广告之前,您不会预先加载广告,这不是非常有效,并且可能会导致广告延迟。

你应该打电话

  interstital = CreateAd() 

在viewDidLoad中,所以它会尽快加载第一个广告。 比您应该使用adMob委托方法

  func interstitialDidDismissScreen(ad: GADInterstitial!) { // load next ad interstital = CreateAd() 

立即加载下一个广告,一旦当前closures。

要使用委托,你可以在ViewController中创build一个扩展

  extension MyViewController: GADInterstitialDelegate { func interstitialDidReceiveAd(ad: GADInterstitial!) { print("AdMob interstitial did receive ad from: \(ad.adNetworkClassName)") } func interstitialWillPresentScreen(ad: GADInterstitial!) { print("AdMob interstitial will present") // pause game/app } func interstitialWillDismissScreen(ad: GADInterstitial!) { print("AdMob interstitial about to be closed") } func interstitialDidDismissScreen(ad: GADInterstitial!) { print("AdMob interstitial closed, reloading...") interstitial = createAd() } func interstitialWillLeaveApplication(ad: GADInterstitial!) { print("AdMob interstitial will leave application") // pause game/app } func interstitialDidFailToPresentScreen(ad: GADInterstitial!) { print("AdMob interstitial did fail to present") } func interstitial(ad: GADInterstitial!, didFailToReceiveAdWithError error: GADRequestError!) { print(error.localizedDescription) } } 

为了确保这些被调用,请在返回广告之前添加此行

  let interstitial = ... interstitial.delegate = self 

最后你的showAd方法应该看起来像这样

  func showAd() { print("doing the showadfunc now") if (interstital.isReady) { print("there is an inter ready") interstital.presentFromRootViewController(self) } else{ print("The interstitial wasn't ready, reloading again.") interstital = CreateAd() } } 

4)如果你正在寻找一个更可重用的解决scheme,你也可以在gitHub上查看我的帮手。

https://github.com/crashoverride777/Swift-AdMob-AppLovinTVOS-CustomAds-Helpers

作为一般的提示,你也应该遵循快速的命名规则,你的func和属性应该以小写字母开头。 只有类,结构,枚举和协议应该以大写字母开头。 它使你的代码更难以阅读,因为它被标记为蓝色但不应该。 你有时在做,有时候不会。

希望这可以帮助

我敢打赌,这是你的问题:

 if (interstital.isReady) { print("there is an inter ready") interstital.presentFromRootViewController(self) interstital = CreateAd() 

您正在展示您的插页式广告,然后立即覆盖您的interstitial 。 您应该实施GADInterstitial的委托方法,并在调用func interstitialDidDismissScreen(ad: GADInterstitial!)调用您的func CreateAd() -> GADInterstitial