I've created an app where you can share your score. It works great on the iPhones, but on the iPads it crashes the app. I keep getting a "Thread 1: signal SIGABRT" in the AppDelegate.
class GameViewController: UIViewController, GameSceneDelegate {
override func viewDidLoad() {
super.viewDidLoad()
if let skView = self.view as? SKView {
if skView.scene == nil{
// create the scene
let scene = GameScene(size: CGSize(width: 2048, height: 1536), delegate: self, gameState: .MainMenu)
skView.showsFPS = false
skView.showsNodeCount = false
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}
self.canDisplayBannerAds = true
}
override func prefersStatusBarHidden() -> Bool {
return true
}
func screenshot() -> UIImage {
UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, 1.0)
view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
func shareString(string: String, url: NSURL, image: UIImage) {
let vc = UIActivityViewController(activityItems: [string, url, image], applicationActivities: nil)
presentViewController(vc, animated: true, completion: nil)
}
}
Please attach this code with your exsiting func shareString
if youractivityView.respondsToSelector("popoverPresentationController") {
youractivityView.popoverPresentationController.sourceView = parentView
}
Related
I am working on SpriteKit Game. From within GameScene i want to represent another viewController. I have done it correctly, but when i dismiss Modally presented viewController, GameScene on my Root viewController freezes. Here is my code on GameScene....
NotificationCenter.default.post(name: NSNotification.Name(rawValue:"present"), object:nil)
Here is my code for root viewController(GameViewController)
override func viewDidLoad() {
super.viewDidLoad()
let gameScene = GameScene()
let skView = self.view as! SKView
skView.showsFPS = true
skView.ignoresSiblingOrder = true
let size = CGSize(width:590, height:390)
/* Set the scale mode to scale to fit the window */
//menuScene.scaleMode = .aspectFit
// menuScene.anchorPoint = CGPoint(x:0, y:0)
//skView.allowsTransparency = true
//size our scene to fit the view exactly:
// let rect1 = CGRect(origin:point, size:size)
//skView.setNeedsUpdateConstraints()
gameScene.size = CGSize(width:size.width, height:size.height)
gameScene.scaleMode = .aspectFill
skView.presentScene(gameScene)
skView.translatesAutoresizingMaskIntoConstraints = false
skView.ignoresSiblingOrder = true
skView.showsFPS = true
skView.showsNodeCount = true
NotificationCenter.default.addObserver(self, selector: #selector(self.presentVC), name: NSNotification.Name(rawValue:"present"), object: nil)
}
override var shouldAutorotate: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if UIDevice.current.userInterfaceIdiom == .phone {
return .allButUpsideDown
} else {
return .all
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
override var prefersStatusBarHidden: Bool {
return true
}
func presentVC(){
let toViewController = viewController() as UIViewController
toViewController.modalPresentationStyle = .overFullScreen
self.present(toViewController, animated: true, completion: nil)
toViewController.transitioningDelegate = self
print("presenting next")
}
And Here is the code for another viewController that is to be represented modally over rootViewController:
override func viewDidLoad() {
super.viewDidLoad()
let imageView = UIImageView(image:UIImage(named:"Background1"))
imageView.frame = CGRect(x:0, y:0, width:1000, height:800)
let aButton = UIButton()
aButton.frame = CGRect(x:view.frame.width/2 - 50, y:view.frame.height/2 - 50, width:100, height:100)
aButton.setTitle("aButton", for: .normal)
aButton.backgroundColor = .green
aButton.addTarget(self, action: #selector(pressed), for: .touchUpInside)
aButton.isEnabled = true
view.addSubview(imageView)
view.addSubview(aButton)
}
func pressed(){
dismissVC()}
override var shouldAutorotate: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if UIDevice.current.userInterfaceIdiom == .phone {
return .allButUpsideDown
} else {
return .all
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
override var prefersStatusBarHidden: Bool {
return true
}
func dismissVC(){
self.dismiss(animated: true, completion: nil)
print("returning previous")
}
Here is the answer with explanation. First of all it was not GameScene in frozen state. But it was view of another viewController that was present even after completion of activity on modally presented viewController. Presence of view of another viewController was due to nonExecution of viewController dismiss code inside that viewController. So presence of another viewController view was not allowing me to interact with my app. Now Solution is, In above Posted question, In GameViewController code i have added presentVC() function. Inside that instead of line:
self.present(toViewController, animated: true, completion: nil)
Use following line:
self.show(toViewController, sender:nil)
EDIT: OK, so this happens even with an empty SpriteKit scene!
What could be wrong here??
Why does iOS need 2 seconds to display SpriteKit scene??
EDIT 2: First time i click on tab bar to display view controller with SKScene it displays immediately, but every next time i try to navigate back to this view controller it will take it 2 seconds to display!
I have a a tab bar controller in my app with multiple different viewControllers.
One of them contains a SpriteKit scene, with a couple of nodes, 5 of them, nothing too heavy.
In simulator everything is fine, but when testing on the device i noticed that sometime there is a big halt ( around 2 seconds! ) when changing to ViewController with the SpriteKit scene.
Other times there is no halt and view is displayed immediately.
Now, i know there must be something I'm doing wrong here, because iOS should definitely be able to handle this.
This is my viewDidLoad function inside the viewController with the spriteKit scene:
override func viewDidLoad() {
super.viewDidLoad()
if let scene = MyScene(fileNamed:"MyScene") {
// Configure the view.
scene.switchView = switchView
let parentNode = scene.childNodeWithName("WholeObject") as! SKSpriteNode
let contentNode = scene.childNodeWithName("CenterNode") as! SKSpriteNode
addPhotoToFrame(contentNode, photoName: "woman", maskName: "circleMask")
let node1 = parentNode.childNodeWithName("node1") as! SKSpriteNode
addPhotoToFrame(zealNode1, photoName: "motherCircleImage", maskName: "circleMaskSmall")
let node2 = parentNode.childNodeWithName("node2") as! SKSpriteNode
addPhotoToFrame(zealNode2, photoName: "hairstylistCircleImage", maskName: "circleMaskSmall")
let node3 = parentNode.childNodeWithName("node3") as! SKSpriteNode
addPhotoToFrame(zealNode3, photoName: "dietCircleImage", maskName: "circleMaskSmall")
let skView = self.view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}
hi deloki i created a new project in swift and come with a solution its working fine on device..... check out my code
here is my GameViewController which call GameScene
import UIKit
import SpriteKit
extension SKNode {
class func unarchiveFromFile1(file : String) -> SKNode? {
if let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks") {
var sceneData = NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe, error: nil)!
var archiver = NSKeyedUnarchiver(forReadingWithData: sceneData)
archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene")
let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as! GameScene
archiver.finishDecoding()
return scene
} else {
return nil
}
}
}
class GameViewController: UIViewController {
var skView:SKView!
override func viewDidLoad() {
super.viewDidLoad()
if let scene = GameScene.unarchiveFromFile1("GameScene") as? GameScene {
// Configure the view.
let graphRect:CGRect = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)
skView = SKView();
skView.frame=graphRect
skView.showsFPS = true
skView.showsNodeCount = true
self.view.addSubview(skView)
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFill
skView.presentScene(scene)
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(3 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue()) {
let s2=GameViewController1();
self.presentViewController(s2, animated: true, completion: { () -> Void in
//
})
}
}
}
override func viewDidDisappear(animated: Bool) {
if((skView) != nil)
{
skView .removeFromSuperview();
skView=nil;
}
}
override func shouldAutorotate() -> Bool {
return true
}
override func supportedInterfaceOrientations() -> Int {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return Int(UIInterfaceOrientationMask.AllButUpsideDown.rawValue)
} else {
return Int(UIInterfaceOrientationMask.All.rawValue)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}
here is my GameViewController1 which call MyScene1
import UIKit
import SpriteKit
extension SKNode {
class func unarchiveFromFile(file : String) -> SKNode? {
if let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks") {
var sceneData = NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe, error: nil)!
var archiver = NSKeyedUnarchiver(forReadingWithData: sceneData)
archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene")
let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as! GameScene
archiver.finishDecoding()
return scene
} else {
return nil
}
}
}
class GameViewController1: UIViewController {
var skView:SKView!
override func viewDidLoad() {
super.viewDidLoad()
if let scene = GameScene.unarchiveFromFile("MyScene1") as? GameScene {
// Configure the view.
let graphRect:CGRect = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)
skView=SKView()
skView.frame=graphRect
skView.showsFPS = true
skView.showsNodeCount = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
// scene.scaleMode = .AspectFill
self.view.addSubview(skView)
skView.presentScene(scene)
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(3 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue()) {
let s2=GameViewController();
self.presentViewController(s2, animated: true, completion: { () -> Void in
//
})
}
}
}
override func viewDidDisappear(animated: Bool) {
if((skView) != nil)
{
skView .removeFromSuperview();
skView=nil;
}
}
override func shouldAutorotate() -> Bool {
return true
}
override func supportedInterfaceOrientations() -> Int {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return Int(UIInterfaceOrientationMask.AllButUpsideDown.rawValue)
} else {
return Int(UIInterfaceOrientationMask.All.rawValue)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}
creating SKview from storyboard i just created it from programmitically and every 2 second i am switching from one view to another and its working fine on all device but one thing i used Xcode 6.4 and ios9
you can download link from http://www.filedropper.com/tryit
I have no idea what triggers the issue but pausing before the view disappeared fixed it for me.
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.contentView.paused = false
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
self.contentView.paused = true
}
I have two problems that I suspect are inter related.
I have a universal app that supports both landscape orientations. My app launches up (with an interface builder launch screen), and then a SKScene is displayed. I have three big problems.
On ipads, and only on iPads (iOS 8, or 9) when the app loads up, all the images are missing from it leaving only the text. Furthermore the display area for the launch screen is about a centimeter smaller then the actual device display. This is not a problem on iPhones
On ipads, and only on iPads (iOS 8, or 9) for some reason the entire app happens with a border around it. The area on the screen my app occupies is smaller then the actual device. This is not a problem on iPhones.
My app is set to auto rotate inside of the "shouldAutoRotate()" function. However I can not get the launch screen to launch in the proper orientation.
I suppose you might be interested to see the following things:
Excerpts from viewController:
import UIKit
import SpriteKit
import AVFoundation
import GameKit
import CoreData
import iAd
extension SKNode {
class func unarchiveFromFile(file : String) -> SKNode? {
if let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks") {
var sceneData = NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe, error: nil)!
var archiver = NSKeyedUnarchiver(forReadingWithData: sceneData)
archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene")
let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as! GameScene
archiver.finishDecoding()
return scene
} else {
return nil
}
}
}
class GameViewController: UIViewController, SceneTransitionDelegate, GKGameCenterControllerDelegate, ADBannerViewDelegate {
var audioPlayers:[AVAudioPlayer] = []
var sounds:[NSURL] = []
var nextSongDelay:NSTimer = NSTimer()
var currentSong:AVAudioPlayer = AVAudioPlayer()
var disp:CGFloat = 0
var starget:String = "HI"
var soundEffects:[AVAudioPlayer] = []
var rwidth:CGFloat = 0
var rheight:CGFloat = 0
var skView:SKView { return view as! SKView }
//var skView:SKView { return view as! SKView }
var iadp:Bool = false
var ar:Bool = true
var uord:Bool = false
override func viewDidLoad() {
super.viewDidLoad()
theEssence = self
launchAudio()
//mediumRectAdView!.delegate = self;
let defaults = NSUserDefaults.standardUserDefaults()
if (isAppAlreadyLaunchedOnce() == false)
{
defaults.setBool(false, forKey: "player")
}
if (defaults.boolForKey("Toothachepunlockiad") == true)
{
s_manualoverride.self = true
iAdBanner.hidden = true
}
// Configure the view.
let skView = self.view as! SKView
//skView.showsFPS = true
//skView.showsNodeCount = true
skView.showsPhysics = false
delli = self
authenticateLocalPlayer()
iAdBanner.frame = CGRectMake(0, self.view.frame.size.height, self.view.frame.width, 50)
iAdBanner.delegate = self
bannerVisible = false
iAdBanner.hidden = false
ar = true
self.shouldAutorotate()
transitionToScene(Menu.self)
}
//SceneTransitionDelegate method
func transitionToScene(sceneClass:Scene.Type) {
playing = false
var sizeRect = UIScreen.mainScreen().applicationFrame
var width = sizeRect.size.width
var height = sizeRect.size.height
let skView = self.view as! SKView
let scene = sceneClass(size: skView.bounds.size)
scene.size = CGSizeMake(width, height)
rwidth = width
rheight = height
swidth = width
sheight = height
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
scene.sceneDelegate = self
skView.presentScene(scene)
}
func transitionToScene(sceneClass: Scene.Type, transitionAnimation: SKTransition)
{
playing = false
var sizeRect = UIScreen.mainScreen().applicationFrame
var width = sizeRect.size.width
var height = sizeRect.size.height
let skView = self.view as! SKView
let scene = sceneClass(size: skView.bounds.size)
scene.size = CGSizeMake(width, height)
rwidth = width
rheight = height
swidth = width
sheight = height
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
scene.sceneDelegate = self
skView.presentScene(scene, transition: transitionAnimation)
}
override func shouldAutorotate() -> Bool {
return ar
}
override func supportedInterfaceOrientations() -> Int {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return Int(UIInterfaceOrientationMask.AllButUpsideDown.rawValue)
} else {
return Int(UIInterfaceOrientationMask.All.rawValue)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
if (playing == true)
{
println("MEMORY WARNING WE ARE DIEING")
//fatalError("MEMORY WARNING WE AARE ALL GOING TO DIE")
}
// Release any cached data, images, etc that aren't in use.
}
override func prefersStatusBarHidden() -> Bool {
return true
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
if(bannerVisible == false) {
// Add banner Ad to the view
if(iAdBanner.superview == nil) {
self.view.addSubview(iAdBanner)
}
// Move banner into visible screen frame:
UIView.beginAnimations("iAdBannerShow", context: nil)
banner.frame = CGRectOffset(banner.frame, 0, -banner.frame.size.height)
UIView.commitAnimations()
bannerVisible = true
}
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
if(bannerVisible == true) {
// Move banner below screen frame:
UIView.beginAnimations("iAdBannerHide", context: nil)
banner.frame = CGRectOffset(banner.frame, 0, banner.frame.size.height)
UIView.commitAnimations()
bannerVisible = false
}
}
func bannerViewActionShouldBegin(banner: ADBannerView!, willLeaveApplication willLeave: Bool) -> Bool {
// Configure the view.
let skView = self.view as! SKView
skView.paused = true
return true
}
func bannerViewActionDidFinish(banner: ADBannerView!) {
let skView = self.view as! SKView
skView.paused = false
}
}
Some things I have recently done that could have triggered this:
Added fabric crash reports
Added auto rotation to it
I had similar problem on iPhone 6 Plus. Reason for that was missing loading images of that device's display size. Check whether you have loading image of all required sizes and orientations. As you can see in the picture, Xcode tells you what size particular image should be. Hope this will fix your issue.
I have implemented iAds in my SpriteKit / Swift game. I cannot find out how to run a function in GameScene when the user clicks on the ad (I have a function that brings up a pause menu) and not just pause the scene. How do I accomplish this? Thanks.
EDIT: This is my GameViewController.
import UIKit
import SpriteKit
import iAd
class GameViewController: UIViewController, ADBannerViewDelegate {
var SH = UIScreen.mainScreen().bounds.height
let transition = SKTransition.fadeWithDuration(1)
var UIiAd: ADBannerView = ADBannerView()
override func viewWillAppear(animated: Bool) {
/* var BV = UIiAd.bounds.height
UIiAd.delegate = self
UIiAd.frame = CGRectMake(0, SH + BV, 0, 0)
self.view.addSubview(UIiAd) */
UIiAd.setTranslatesAutoresizingMaskIntoConstraints(false)
UIiAd.delegate = self
self.view.addSubview(UIiAd)
let viewsDictionary = ["bannerView":UIiAd]
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[bannerView]|", options: .allZeros, metrics: nil, views: viewsDictionary))
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[bannerView]|", options: .allZeros, metrics: nil, views: viewsDictionary))
}
override func viewWillDisappear(animated: Bool) {
UIiAd.delegate = nil
UIiAd.removeFromSuperview()
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
var BV = UIiAd.bounds.height
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1) // Time it takes the animation to complete
UIiAd.alpha = 1 // Fade in the animation
UIView.commitAnimations()
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1)
UIiAd.alpha = 0
UIView.commitAnimations()
}
func showBannerAd() {
UIiAd.hidden = false
var BV = UIiAd.bounds.height
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(10) // Time it takes the animation to complete
UIiAd.frame = CGRectMake(0, SH - BV, 2048, 0) // End position of the animation
UIView.commitAnimations()
}
func hideBannerAd() {
UIiAd.hidden = true
var BV = UIiAd.bounds.height
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1) // Time it takes the animation to complete
UIiAd.frame = CGRectMake(0, SH + BV, 0, 0) // End position of the animation
UIView.commitAnimations()
}
override func viewDidLoad() {
super.viewDidLoad()
self.UIiAd.hidden = true
self.UIiAd.alpha = 0
NSNotificationCenter.defaultCenter().addObserver(self, selector: "hideBannerAd", name: "hideadsID", object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "showBannerAd", name: "showadsID", object: nil)
let scene = MainMenu(size: CGSize(width: 2048, height: 1356))
let skView = self.view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
override func prefersStatusBarHidden() -> Bool {
return true
}
Then in the GameScene I import iAd, add ADBannerViewDelegate, then add this code
var iAdBanner: ADBannerView = ADBannerView()
func showAds(){
NSNotificationCenter.defaultCenter().postNotificationName("showadsID", object: nil)
}
func bannerViewActionShouldBegin(banner: ADBannerView!, willLeaveApplication willLeave: Bool) -> Bool {
iAdBanner.delegate = self
println("Clicked")
paused = true
return true
}
Try this function for banner iAd:
func bannerViewActionShouldBegin(banner: ADBannerView!, willLeaveApplication willLeave: Bool) -> Bool {
println("Clicked")
// If you want to pause game scene:
let skView: SKView = self.view as! SKView
skView.scene.paused = true
return true
}
and also:
func bannerViewActionDidFinish(banner: ADBannerView!) {
println("Closed")
// If you want to continue game scene:
let skView: SKView = self.view as! SKView
skView.scene.paused = false
}
I made simple game with Swift and SpriteKit. Everything seems to work but I have a problem with my iAd Setup. I only want to show the ad banner in specific scenes (main menu and game over) not during the gameplay.
My iAd setup works but only if it is displayed all the time.
My last attempt to fix it was with the NSNotificationCenter method. I have done it as I have seen it in other question/answers here but the app crashes immediately after launch.
Hope that someone could help me. Just let me know if you need more of my code.
Thanks in advance.
GameViewController.swift
class GameViewController: UIViewController, ADBannerViewDelegate {
var adBannerView = ADBannerView(frame: CGRect.zeroRect)
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "handleNotification", name: "hideAd", object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "handleNotification", name: "showAd", object: nil)
self.adBannerView.delegate = self
self.adBannerView.hidden = true
adBannerView.center = CGPoint(x: adBannerView.center.x, y: view.bounds.size.height - adBannerView.frame.size.height / 2)
view.addSubview(adBannerView)
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
// Configure the view.
let skView = self.view as SKView
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
var scene: SKScene = MainMenu(size: skView.bounds.size)
scene.scaleMode = SKSceneScaleMode.AspectFill
skView.presentScene(scene)
}
}
func handleNotification(notification: NSNotification){
if notification.name == "hideAd"{
adBannerView.hidden = true
}else if notification.name == "showAd"{
adBannerView.hidden = false
}
}
//iAD Setup
func bannerViewWillLoadAd(banner: ADBannerView!) {
println("Ad loads")
}
func bannerViewDidLoadAd(banner: ADBannerView!){
println("Ad loaded")
self.adBannerView.hidden = false
}
func bannerViewActionDidFinish(banner: ADBannerView!) {
println("resume scene")
let skView = self.view as SKView
skView.paused = false
}
func bannerViewActionShouldBegin(banner: ADBannerView!, willLeaveApplication willLeave: Bool) -> Bool {
println("pause scene")
let skView = self.view as SKView
skView.paused = true
return true
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
println("Failed to load ad")
self.adBannerView.hidden = true
} more code....
MainMenu.swift
class MainMenu: SKScene{
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override init(size:CGSize){
super.init(size: size)
NSNotificationCenter.defaultCenter().postNotificationName("showAd", object: nil)
more code...
This works for me
In my view controller I have this code:
// Banner Ad
var SH = UIScreen.mainScreen().bounds.height
let transition = SKTransition.fadeWithDuration(1)
var UIiAd: ADBannerView = ADBannerView()
override func viewWillAppear(animated: Bool) {
var BV = UIiAd.bounds.height
UIiAd.delegate = self
UIiAd.frame = CGRectMake(0, SH + BV, 0, 0)
self.view.addSubview(UIiAd)
}
override func viewWillDisappear(animated: Bool) {
UIiAd.delegate = nil
UIiAd.removeFromSuperview()
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
var BV = UIiAd.bounds.height
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1) // Time it takes the animation to complete
UIiAd.alpha = 1 // Fade in the animation
UIView.commitAnimations()
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1)
UIiAd.alpha = 0
UIView.commitAnimations()
}
func showBannerAd() {
UIiAd.hidden = false
var BV = UIiAd.bounds.height
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1) // Time it takes the animation to complete
UIiAd.frame = CGRectMake(0, SH - BV, 0, 0) // End position of the animation
UIView.commitAnimations()
}
func hideBannerAd() {
UIiAd.hidden = true
var BV = UIiAd.bounds.height
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1) // Time it takes the animation to complete
UIiAd.frame = CGRectMake(0, SH + BV, 0, 0) // End position of the animation
UIView.commitAnimations()
}
override func viewDidLoad() {
super.viewDidLoad()
self.UIiAd.hidden = true
self.UIiAd.alpha = 0
NSNotificationCenter.defaultCenter().addObserver(self, selector: "hideBannerAd", name: "hideadsID", object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "showBannerAd", name: "showadsID", object: nil)
let scene = GameScene()
// Configure the view.
let skView = self.view as SKView
skView.showsFPS = false
skView.showsNodeCount = false
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFit
scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
scene.size = skView.bounds.size
skView.presentScene(scene, transition: transition)
}
To display it in the scene I want (for me it's the GameOver scene) I did this:
override func didMoveToView(view: SKView) {
showAds()
// Rest of your code here...
}
func showAds(){
NSNotificationCenter.defaultCenter().postNotificationName("showadsID", object: nil)
}
Basically this code creates a banner off the scene, and when the banner is loaded and the scene gets called, it slides up from the bottom. When you switch scenes, it offsets it again and when you come back to that scene, it slides up from the bottom again. If the banner doesn't load, it's off screen so no worries about it showing a white bar. Also, it sets the alpha to 0 if it doesn't load just in case (makes it invisible). Hope this helps.
I USE THIS TO PRESENT THE iAd Banner in subview
var vc = self.view?.window?.rootViewController
vc?.view.addSubview(adView!)
When I want to hide it when in the game (because iAd reduce FPS) I call
adView!.removeFromSuperview()
When the user finished the Game just add
var vc = self.view?.window?.rootViewController
vc?.view.addSubview(adView!)
to show the iAd banner again
BUT YOU NEED TO IMPLEMENT THIS CODE IN GameViewController
class GameViewController: ADBannerViewDelegate (you needed this too)
also don't forget to import iAd at the top of gameviewcontroller
also import iAd framework to the project
override func viewDidLoad() {
self.ShowAd()
//Have this in view didLoad too
func ShowAd() {
super.viewDidLoad()
adView = ADBannerView(adType: ADAdType.Banner)
adView!.delegate = self
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
self.view.addSubview(adView!)
self.view.layoutIfNeeded()
println("Pass")
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
adView!.removeFromSuperview()
/*var alert = UIAlertController(title: "iAd Message", message:
"iAd Fail To Load", preferredStyle: UIAlertControllerStyle.Alert)
self.presentViewController(alert, animated: false, completion: nil)
alert.addAction(UIAlertAction(title: "dismiss", style: UIAlertActionStyle.Default,
handler: nil))
self.view.layoutIfNeeded()*/
println("fail")
}