0

Whenever I run my app the following error is called

Warning: Attempt to present "The alert" on "MenuViewController" whose view is not in the window hierarchy!

what exactly does this mean and how do I fix it?

I only have one UIViewController and here it is

class MenuViewController: UIViewController {


    var iMinSessions = 3
    var iTryAgainSessions = 6



    func rateMe() {
        var neverRate = NSUserDefaults.standardUserDefaults().boolForKey("neverRate")
        var numLaunches = NSUserDefaults.standardUserDefaults().integerForKey("numLaunches") + 1

        if (!neverRate && (numLaunches == iMinSessions || numLaunches >= (iMinSessions + iTryAgainSessions + 1)))
        {
            showRateMe()
            numLaunches = iMinSessions + 1
        }
        NSUserDefaults.standardUserDefaults().setInteger(numLaunches, forKey: "numLaunches")
    }





    func showRateMe() {
        var alert = UIAlertController(title: "Rate Me", message: "Thanks for playing Pong Ball", preferredStyle: UIAlertControllerStyle.Alert)

        alert.addAction(UIAlertAction(title: "Rate Pong Ball!", style: UIAlertActionStyle.Default, handler: { alertAction in
            UIApplication.sharedApplication().openURL(NSURL(string : "itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=<iTUNES CONNECT APP ID>")!)

            alert.dismissViewControllerAnimated(true, completion: nil)
        }))

        alert.addAction(UIAlertAction(title: "No Thanks", style: UIAlertActionStyle.Default, handler: { alertAction in
            NSUserDefaults.standardUserDefaults().setBool(true, forKey: "neverRate")

            alert.dismissViewControllerAnimated(true, completion: nil)

        }))
        alert.addAction(UIAlertAction(title: "Maybe Later", style: UIAlertActionStyle.Default, handler: { alertAction in
            alert.dismissViewControllerAnimated(true, completion: nil)
        }))


        self.presentViewController(alert, animated: true, completion: nil)
    }






    override func viewDidLoad() {
        super.viewDidLoad()

//        Calling it

        rateMe()

        let skView = view as! SKView
        var scene = MenuScene(size: skView.bounds.size)
        skView.ignoresSiblingOrder = true
        scene.scaleMode = .AspectFill
        skView.presentScene(scene)
            }

    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()
    }
    override func prefersStatusBarHidden() -> Bool {
        return true
    }
}
Matt
  • 89
  • 7

1 Answers1

2

In viewDidLoad your view has not been displayed yet. Move the call to rate it me from viewDidLoad to viewDidAppear.

EDIT

Since it's a rate me. I think better it's put in appDelegate in applicationDidFinishLaunchWithOptions.

Community
  • 1
  • 1
Omar Al-Shammary
  • 304
  • 3
  • 13
  • I was with you until your edit. If viewDidLoad is too early, then so is applicationDidFinishLaunchWithOptions. – Mick MacCallum Jun 17 '15 at 22:39
  • It's not that it's too early or not. It's the fact viewDidAppear is called every time your view appears. It really depends on your requirements where you wanna put it. But app delegate seems to be the ideal place. – Omar Al-Shammary Jun 18 '15 at 00:11