I've been trying to add an Admob banner advertisement to my spritekit game, and although I've been successful in getting the advertisement to show up initially in the first scene of the game (MenuScene), when I leave that scene (to go to GameScene, SettingsScene, etc.) and then return to the menu scene, I get the error: unexpectedly found nil while unwrapping an Optional value
我一直试图在我的spritekit游戏中添加一个Admob横幅广告,虽然我已经成功地让广告最初出现在游戏的第一个场景(MenuScene)中,但是当我离开那个场景时(去)到GameScene,SettingsScene等)然后返回到菜单场景,我得到错误:在解包一个Optional值时意外发现了nil
Basically, whenever I leave MenuScene, the banner ad variable becomes nil, and when I return to it the game bugs out because it's trying to call on a nil value.
基本上,每当我离开MenuScene时,横幅广告变量都变为零,当我回到它时,游戏就会出错,因为它试图调用零值。
I have tried initializing the banner ad in the GameViewController, MenuScene, and SettingsScene (with the methods remaining in GameViewController and just being called in the MenuScene or SettingsScene in the two latter options) - the banner ad always became when leaving the menu scene, and was nil upon arrival in the settings scene.
我尝试在GameViewController,MenuScene和SettingsScene中初始化横幅广告(GameViewController中保留的方法只是在后两个选项中的MenuScene或SettingsScene中调用) - 横幅广告在离开菜单场景时总是变成了,到达设置场景后没有。
I suspect that my problem may have something to do with the fact that the GameViewController is only directly related to the MenuScene, and that when the player transitions away from MenuScene (and consequently away also from GameViewController) to another scene, all the variables in GameViewController become nil. However, I have no idea what to do, and would appreciate some help in this regard. Here is my initialization code:
我怀疑我的问题可能与GameViewController只与MenuScene直接相关这一事实有关,当玩家从MenuScene转移(因此也离开GameViewController)到另一个场景时,GameViewController中的所有变量变得零。但是,我不知道该怎么做,并希望在这方面提供一些帮助。这是我的初始化代码:
In GameViewController:
在GameViewController中:
var bannerAd: GADBannerView!
func initializeBanner() {
bannerAd = GADBannerView(adSize: kGADAdSizeSmartBannerLandscape, origin: CGPoint(x: 0, y: self.view.frame.size.height-32))
bannerAd.isHidden = true
bannerAd.adUnitID = "ca-app-pub-3940256099942544/2934735716"
bannerAd.rootViewController = self
view.addSubview(bannerAd)
}
func requestBanner() {
let request = GADRequest()
request.testDevices = ["31340db3ea728bd5faf2789325b27620"]
bannerAd.load(request)
}
In MenuScene:
在MenuScene中:
var gameVC: GameViewController!
override func didMove(to view: SKView) {
gameVC.initializeBanner()
gameVC.requestBanner()
gameVC.bannerAd.isHidden = false
}
When transitioning to (for example) SettingsScene:
转换到(例如)SettingsScene时:
gameVC.bannerAd.isHidden = true
1 个解决方案
#1
2
As you mentioned you will loose the reference to your GameViewController when you change scenes. In general its not the best practice to reference the GameViewController in your SKScenes.
正如您所提到的,当您更改场景时,您将松开对GameViewController的引用。一般来说,这不是在SKScenes中引用GameViewController的最佳实践。
A better approach to call the GameViewController method would be using Notification Center or delegation.
调用GameViewController方法的更好方法是使用通知中心或委托。
Create a key for your notification to avoid typos. You can put this anywhere you like in your project (outside any class or a new .swift file)
为通知创建密钥以避免拼写错误。您可以将它放在项目中的任何位置(任何类或新的.swift文件之外)
extension Notification.Name {
static let showBannerAd = Notification.Name(rawValue: "ShowBanner")
}
Than in your GameViewController add the observer in ViewDidLoad to call the requestBanner method
比在GameViewController中添加ViewDidLoad中的观察者来调用requestBanner方法
NotificationCenter.default.addObserver(self, selector: #selector(requestBanner), name: .showBannerAd, object: nil) // selector is the method to call
and than in your SKScene(s) you can post the notification like so when you need to show the banner.
而在您的SKScene中,您可以在需要显示横幅时发布通知。
NotificationCenter.default.postNotificationName(.showBannerAd, object: nil)
How to present ads during certain scenes in sprite-kit?
如何在sprite-kit的某些场景中展示广告?
Also to avoid such crashes you should not force unwrap your properties (!) unless you know 100% that it will not be nil. By writing
另外,为避免此类崩溃,您不应强制拆开您的属性(!),除非您100%知道它不会为零。通过写作
var bannerAd: GADBannerView!
you tell xCode that this banner property will always be there and will never be nil. Thats not the case tho and thus makes your code less solid. So instead you should make it an optional property like this
你告诉xCode这个横幅属性将永远存在,永远不会是零。这不是案例,因此使您的代码不那么稳固。所以你应该把它变成像这样的可选属性
var bannerAd: GADBannerView?
and than your setup method like this
而不是像你这样的设置方法
func initializeBanner() {
bannerAd = GADBannerView(adSize: kGADAdSizeSmartBannerLandscape, origin: CGPoint(x: 0, y: self.view.frame.size.height-32))
bannerAd?.isHidden = true
bannerAd?.adUnitID = "ca-app-pub-3940256099942544/2934735716"
bannerAd?.rootViewController = self
view.addSubview(bannerAd!)
}
Now when the banner property is nil you will not crash when for example saying this
现在,当banner属性为nil时,例如说这个就不会崩溃
bannerAd?.isHidden = true
Alternatively I have a helper on Github which will make this much easier and cleaner.
或者我在Github上有一个帮手,这将使这更容易和更清洁。
https://github.com/crashoverride777/SwiftyAds
https://github.com/crashoverride777/SwiftyAds
Hope this helps
希望这可以帮助
#1
2
As you mentioned you will loose the reference to your GameViewController when you change scenes. In general its not the best practice to reference the GameViewController in your SKScenes.
正如您所提到的,当您更改场景时,您将松开对GameViewController的引用。一般来说,这不是在SKScenes中引用GameViewController的最佳实践。
A better approach to call the GameViewController method would be using Notification Center or delegation.
调用GameViewController方法的更好方法是使用通知中心或委托。
Create a key for your notification to avoid typos. You can put this anywhere you like in your project (outside any class or a new .swift file)
为通知创建密钥以避免拼写错误。您可以将它放在项目中的任何位置(任何类或新的.swift文件之外)
extension Notification.Name {
static let showBannerAd = Notification.Name(rawValue: "ShowBanner")
}
Than in your GameViewController add the observer in ViewDidLoad to call the requestBanner method
比在GameViewController中添加ViewDidLoad中的观察者来调用requestBanner方法
NotificationCenter.default.addObserver(self, selector: #selector(requestBanner), name: .showBannerAd, object: nil) // selector is the method to call
and than in your SKScene(s) you can post the notification like so when you need to show the banner.
而在您的SKScene中,您可以在需要显示横幅时发布通知。
NotificationCenter.default.postNotificationName(.showBannerAd, object: nil)
How to present ads during certain scenes in sprite-kit?
如何在sprite-kit的某些场景中展示广告?
Also to avoid such crashes you should not force unwrap your properties (!) unless you know 100% that it will not be nil. By writing
另外,为避免此类崩溃,您不应强制拆开您的属性(!),除非您100%知道它不会为零。通过写作
var bannerAd: GADBannerView!
you tell xCode that this banner property will always be there and will never be nil. Thats not the case tho and thus makes your code less solid. So instead you should make it an optional property like this
你告诉xCode这个横幅属性将永远存在,永远不会是零。这不是案例,因此使您的代码不那么稳固。所以你应该把它变成像这样的可选属性
var bannerAd: GADBannerView?
and than your setup method like this
而不是像你这样的设置方法
func initializeBanner() {
bannerAd = GADBannerView(adSize: kGADAdSizeSmartBannerLandscape, origin: CGPoint(x: 0, y: self.view.frame.size.height-32))
bannerAd?.isHidden = true
bannerAd?.adUnitID = "ca-app-pub-3940256099942544/2934735716"
bannerAd?.rootViewController = self
view.addSubview(bannerAd!)
}
Now when the banner property is nil you will not crash when for example saying this
现在,当banner属性为nil时,例如说这个就不会崩溃
bannerAd?.isHidden = true
Alternatively I have a helper on Github which will make this much easier and cleaner.
或者我在Github上有一个帮手,这将使这更容易和更清洁。
https://github.com/crashoverride777/SwiftyAds
https://github.com/crashoverride777/SwiftyAds
Hope this helps
希望这可以帮助