这很长,但它可能是一个非常简单的修复方法。 大部分内容都是代码,只是跳到底部,然后就是tl; dr
嘿,所以我已经关注了让我在Swift Spritekit游戏中使用Admob插页式广告的10个教程。除了我见过的所有教程之外,我都使用带按钮的IBAction。 目前我希望广告在菜单上偶尔弹出一次。 (刚开始,我可能会在以后更改)。 这一切都很完美,但是一旦我点击播放按钮(转到不同的场景),然后返回到菜单场景。 (GameScene)不再发生插页式功能。没有任何错误,只有在应用程序完全关闭并重新打开之后才会再执行此操作。
这是代码。
在我的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类中,我有以下功能:
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课程中,我有这个功能来显示插页式广告。
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中),(我已经确认它至少认为它正在调用函数。)它完美地工作时该应用程序开始打开。但是当我改变场景然后返回菜单场景(GameScene)时,我的GameScene函数中的Prints继续发生,我的代码认为它正在调用ShowAd函数,但似乎没有什么是正在发生,没有插页式广告,甚至不是GameViewController中ShowAd功能中的打印件。
所以看起来在我更改场景并返回后,我的游戏忘记了GameViewController的内容。如果我在没有'?'的情况下引用GameViewController?它会因为错误而崩溃我的游戏"在打开一个可选项时,意外地发现了nil。"所以改变场景后,GameViewController可能变成零吗?我该如何解决这个问题。
请帮帮我!!! (我不熟悉编程,以防你无法告诉。我知道对我的代码进行讽刺评论一定很诱人,它真的很简单,而且目前还不是很好。)
非常感谢你,如果你可以帮助我,哇...感谢阅读所有这些......;)
答案 0 :(得分:1)
您最有可能的问题是,一旦转换到新场景,viewController属性将设置为nil,因此如果您使用!则会崩溃。
一般来说,不是在SKScenes中引用viewController的最佳实践,您应该使用Delegation或NSNotification Center。
1)通知中心(最简单的方法)
在具有展示广告功能的ViewController中,在ViewDidLoad中添加NSNotificationCenter观察器
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(showAd), name: "ShowInterAdKey", object: nil)
(Selector是要调用的函数,name是引用此观察者的键)
当您想要展示广告时,只需在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()
在当前广告关闭后立即加载下一个广告。
要使用委托,您可以在ViewController
中创建扩展 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)
}
}
要确保调用这些内容,请转到您的createAd函数并在返回广告之前添加此行
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)如果您正在寻找更可重复使用的解决方案,您还可以在gitHub上查看我的助手。
https://github.com/crashoverride777/Swift-AdMob-AppLovinTVOS-CustomAds-Helpers
作为一般提示,您还应遵循快速命名约定,您的func和属性应以小写字母开头。只有类,结构,枚举和协议应以大写字母开头。 它使您的代码更难以自己和stackoverflow读取,因为它标记为蓝色但不应该。你有时做,有时不做。
希望这有帮助
答案 1 :(得分:1)
我敢打赌这是你的问题:
if (interstital.isReady) {
print("there is an inter ready")
interstital.presentFromRootViewController(self)
interstital = CreateAd()
您正在展示您的插页式广告,然后立即覆盖您的interstitial
。您应该实施GADInterstitial
的委托方法,并在调用func CreateAd() -> GADInterstitial
后致电func interstitialDidDismissScreen(ad: GADInterstitial!)
。
答案 2 :(得分:0)
如果您的设备由于以下原因而崩溃:
interstitial.delegate = self
然后将其放在CreatAndLoadInterstitial()中,而不是viewDidLoad()