I have my interstitial ads set up in a way where if the user dies 4 times then a full page ads pops up. numberOfLoses increases everytime the player dies.
numberOfLosses++
if numberOfLosses == 4 {
gameViewController?.showFullScreenAd()
numberOfLosses = 0
}
this works on the simulator and on my device the first time, but then i never see it working again, no matter how many times I die. Is this something that will work once its live on the app store or am i doing something wrong?
func showFullScreenAd() {
interstitial.delegate = self
self.interstitialPresentationPolicy = ADInterstitialPresentationPolicy.Manual
self.requestInterstitialAdPresentation()
}
if i println(self.requestInterstitialAdPresentation()) i get false after the first time
here is my updated code (works but multiple ads being loaded at same time)
//MARK: interstitial ad delegate
func showFullScreenAd() {
viewForAd = UIView(frame: screenbounds)
viewForAd.frame = CGRectOffset(viewForAd.frame, 0, screenbounds.size.height)
self.view.addSubview(viewForAd)
iADInterstitial = ADInterstitialAd()
iADInterstitial.delegate = self
self.interstitialPresentationPolicy = ADInterstitialPresentationPolicy.Manual
self.requestInterstitialAdPresentation()
}
func interstitialAdDidUnload(interstitialAd: ADInterstitialAd!) {
iADInterstitial = nil
println("did unload")
}
func interstitialAd(interstitialAd: ADInterstitialAd!, didFailWithError error: NSError!) {
viewForAd.removeFromSuperview()
viewForAd = nil
iADInterstitial = nil
println("failed with error: \(error.localizedDescription)")
}
func interstitialAdDidLoad(interstitialAd: ADInterstitialAd!) {
println("Ad did load")
iADInterstitial.presentInView(viewForAd)
UIView.beginAnimations("", context: nil)
viewForAd.frame = CGRectOffset(viewForAd.frame, 0, -screenbounds.size.height)
UIView.commitAnimations()
}
func interstitialAdActionDidFinish(interstitialAd: ADInterstitialAd!) {
UIView.beginAnimations("", context: nil)
viewForAd.frame = CGRectOffset(viewForAd.frame, 0, screenbounds.size.height)
UIView.commitAnimations()
println("action did finish")
}
You don't need interstitial.delegate = self (and whatever other code you've not shown that goes along with it.)
You only need two or three lines of code:
// Preloads an ad, so call on app startup (optional but recommended).
[UIViewController prepareInterstitialAds];
// Call once on your viewController when you create it.
self.interstitialPresentationPolicy = ADInterstitialPresentationPolicyManual;
// Call when you want to show an ad (will show if one is available)
[self requestInterstitialAdPresentation];
Thats all there is to the new methods in iOS 7. Whatever other code you have may be causing problems so remove it, and if you still have problems (especially in test with 100% fill rate) then that needs further investigation.
Related
The test ad works fine when I don't include the in app purchase. I click on the cell, it takes me to the next view controller, and the ad pops up. However, when I include in-app purchases the ad doesn't show up even if the user didn't pay to remove ads.
The ad shows up with this function:
func showAd() {
self.interstitial = createInterstitialAd()
}
But when I add this, the ad doesn't show even if the user hasn't paid to remove ads.
func showAd() {
if let purchased = UserDefaults.standard.value(forKey: "payment") as? Bool{
if purchased == true{
interstitial = nil
print("there is no ad!!!!")
}else{
self.interstitial = createInterstitialAd()
print("there is an ad!!!")
}
}
Your problem is that initially there will be no value in UserDefaults for the payment key. This will cause the outer if statement to fall through, resulting in no ad.
You can make your code simpler by using bool(forKey:) - This will return false where the key is not present in UserDefaults rather than nil:
func showAd() {
if UserDefaults.standard.bool(forKey: "payment") {
interstitial = nil
print("there is no ad!!!!")
} else {
self.interstitial = createInterstitialAd()
print("there is an ad!!!")
}
}
I've launched an iOS app, but I am having problems loading rewarded video ads using the Google Mobile Ads SDK.
When a player clicks the button to see a video ad, the player is shown a video very few times. Most of the time, the user is shown an error of Admob being unable to fill the request:
Error Domain=com.google.ads Code=1 "Request Error: No ad to show."
Sometimes it will take them several clicks before getting one, and sometimes they just can't get one no matter how many clicks. This issue happens more with my rewarded videos, but it also happens with my banner ad. Sometimes Google is unable to provide me with a banner ad. Does anyone know why this is not working?
My code for ads:
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
// Load the SKScene from 'GameScene.sks'
let scene = MainMenu(view.bounds.size, self, nil)
scene.scaleMode = .aspectFill
// Present the scene
view.presentScene(scene)
view.ignoresSiblingOrder = true
view.showsFPS = false
view.showsNodeCount = false
view.showsPhysics = false
GADRewardBasedVideoAd.sharedInstance().delegate = self
GADRewardBasedVideoAd.sharedInstance().load(getRequest(),
withAdUnitID: rewardAdId)
// In this case, we instantiate the banner with desired ad size.
if GameViewController.bannerView == nil {
GameViewController.bannerView = GADBannerView(adSize: kGADAdSizeBanner)
GameViewController.bannerView.adUnitID = bannerId
GameViewController.bannerView.rootViewController = self
GameViewController.bannerView.load(getRequest())
GameViewController.bannerView.isHidden = true
addBannerViewToView(GameViewController.bannerView)
}
authenticateLocalPlayer()
QuestManager().checkForRefresh()
}
}
public func getRequest() -> GADRequest {
let request = GADRequest()
return request
}
public func displayRewardedVideo() {
if GADRewardBasedVideoAd.sharedInstance().isReady {
GADRewardBasedVideoAd.sharedInstance().present(fromRootViewController: self)
} else {
GameViewController.loadVideo()
}
}
public static func loadVideo(){
if !GADRewardBasedVideoAd.sharedInstance().isReady {
GADRewardBasedVideoAd.sharedInstance().load(GADRequest(),
withAdUnitID: rewardAdId)
}
}
func rewardBasedVideoAdDidClose(_ rewardBasedVideoAd: GADRewardBasedVideoAd) {
GADRewardBasedVideoAd.sharedInstance().load(getRequest(),
withAdUnitID: rewardAdId)
if let scene = gameScene {
scene.audioManager.unmmute()
}
print("Video did close")
}
I am currently working at a certain company that provides tons of free mobile applications with Admob as a freelancer, so I'm quite adept with it.
Anyways, what I've learned from the manager of my company (they also have a Google Admob consultant there), is that the ad to be shown in an app can be dependent to the country that the user is in. For instance, I'm here in South East Asia and they're in Europe. I experience some times when I do not receive a banner ad, but in their place, they always receive all types of ads.
As long as your project is complying the the Google Admob's rules (e.g. do not display interstitial ad after the other one at a short gap of time), and you receive some ad at least once every while, then I believe you're doing fine.
I hope this helps.
I have this code:
func createAndLoadInterstitial() {
interstitial = GADInterstitial(adUnitID: "ca-app-pub-xxxxxxxxxx/xxxxx")
interstitial.delegate = self
let request = GADRequest()
interstitial.loadRequest(request)
}
override func viewDidAppear(animated: Bool) {
if (interstitial.isReady && showAd) {
showAd = false
// print("iterstitialMain is ready")
interstitial.presentFromRootViewController(self)
self.createAndLoadInterstitial()
}
else {
showAd = true
}
}
and it works. But it shows an ad every time the user taps on the back button.
I want to show an ad only one time when the user taps on the back button. Would it be better to show an ad after some time instead? For example, every 5 minutes?
Where are you setting showAd to true initially? The logic in your if statement is the main issue.
After you set showAd = false in your if statement, the next time viewDidAppear is called your else statement will be executed, setting showAd back to true.
What you should do is check your Bool, and then check interstitial.isReady. Then, in your GADInterstitial's interstitialDidDismissScreen delegate method you would update your showAd Bool and request another GADInterstitial if you'd like. You say you only want to show one GADInterstitial so requesting another is not necessary. For example:
override func viewDidAppear(animated: Bool) {
if showAd { // Should we show an ad?
if interstitial.isReady { // Is the ad ready?
interstitial.presentFromRootViewController(self)
}
}
else {
// Do nothing
}
}
func interstitialDidDismissScreen(ad: GADInterstitial!) {
// Ad was presented and dismissed
print("interstitialDidDismissScreen")
showAd = false // Don't show anymore ads
}
Also, you can change:
let request = GADRequest()
interstitial.loadRequest(request)
to just:
interstitial.loadRequest(GADRequest())
in your createAndLoadInterstitial function.
To answer the second part of your question asking if you should present an ad after some time delay, that is a violation of the AdMob program policies.
Examples of non-compliant implementations:
Interstitial ads that appear before the app has opened or after the app has closed.
Interstitial ads that are triggered after a user closes another interstitial ad.
Interstitial ads loading unexpectedly while a user is viewing the app’s content. Remember to only serve interstitials between pages of content.
Interstitial ads that trigger after every user click.
Interstitial ads that appear during periods of game play or heavy user interaction.
I am trying to load this google interstitial ad when the game is over.
if (self.interstitial.isReady)
{
self.interstitial.presentFromRootViewController(self)
}
But I am getting an error that says "Cannot convert value of type 'GameScene' to expected argument type 'UIViewController!".
I have used the same lines of code with my other apps that don't use sprite kit, is it different with sprite kit?
Yes it's different in SpriteKit because you trying to present from a SKScene and not a UIViewController.
Try this and see if it works
if (self.interstitial.isReady) {
self.interstitial.presentFromRootViewController(self.view?.window?.rootViewController)
}
If you are getting a nil crash now than you did not init the ad property correctly. You should also have some checks to ensure this does not happen.
This is how the adMob code from my gitHub helper looks.
You should have a property like so
var interstitial: GADInterstitial?
Than in view didLoad you should preload the ad
interstitial = adMobLoadInterAd()
This is pre-loading code.
func adMobLoadInterAd() -> GADInterstitial {
Debug.print("AdMob inter loading...")
let googleInterAd = GADInterstitial(adUnitID: "Your adMob ID")
googleInterAd.delegate = self
let request = GADRequest()
request.testDevices = [kGADSimulatorID] // DEBUG only
googleInterAd.loadRequest(request)
return googleInterAd
}
Than when you want to show an ad you call this
func adMobShowInterAd() {
guard interstitial != nil && interstitial!.isReady else { // calls interDidReceiveAd
Debug.print("AdMob inter is not ready, reloading")
interstitial = adMobLoadInterAd()
return
}
Debug.print("AdMob inter showing...")
interstitial?.presentFromRootViewController(self.view?.window?.rootViewController)
}
Than finally in the delegate methods you should pre load a new ad when the current ad is dismissed.
func interstitialDidDismissScreen(ad: GADInterstitial!) {
Debug.print("AdMob inter closed")
interstitial = adMobLoadInterAd()
}
I've tried a whole bunch of ways to get Game Center working in my SpriteKit game. Unfortunately the way I've done it in the past using ObjC and ViewControllers don't work because I'm using SKScene/ a GameScene.
This is the swift version of the code (I think):
// MARK: Game Center Integration
//login and make available
func authenticateLocalPlayer(){
let localPlayer = GKLocalPlayer()
print(localPlayer)
localPlayer.authenticateHandler = {(viewController, error) -> Void in
if ((viewController) != nil) {
self.presentViewController(viewController!, animated: true, completion: nil)
}else{
print((GKLocalPlayer.localPlayer().authenticated))
}
}
}
//submit a score to leaderboard
func reportScoreToLeaderboard(thisScore:Int){
if GKLocalPlayer.localPlayer().authenticated {
let scoreReporter = GKScore(leaderboardIdentifier: "LeaderboardID")
scoreReporter.value = Int64(thisScore)
let scoreArray: [GKScore] = [scoreReporter]
GKScore.reportScores(scoreArray, withCompletionHandler: { (error: NSError?) -> Void in
if error != nil {
print(error!.localizedDescription)
} else {
print("Score submitted")
}
})
}
}
//show leaderboard (call from button or touch)
func showLeaderboard() {
let vc = self.view?.window?.rootViewController
let gc = GKGameCenterViewController()
gc.gameCenterDelegate = self
vc?.presentViewController(gc, animated: true, completion: nil)
}
//hides view when finished
func gameCenterViewControllerDidFinish(gameCenterViewController: GKGameCenterViewController){
gameCenterViewController.dismissViewControllerAnimated(true, completion: nil)
}
Unfortunetely, no matter what I try, I either get this error:
Attempting to load the view of a view controller while it is deallocating is not allowed and may result in undefined behavior
... or it just crashes.
I've read that NSNotifications can be used? But how?
I'm guessing the best way is to set it all up in the GameViewController.swift and use NSNotifications to communicate with the RootViewController from the GameScene? I can't seem to find a tutorial or example though.
Use delegation when a view controller needs to change views, do not have the view itself change views, this could cause the view trying to deallocating while the new view is being presented, thus the error you are getting