I'm working in Spritekit and I'm trying to present a UIAlertController from my SKScene, but I am having trouble doing it. I've watched several tutorials but none of the UIAlertController tutorials have been specific to Spritekit. I keep seeing this code below, but it has not been effective since SKScene is not a UIViewController.
[self presentViewController:self animated:YES completion:nil];
I have the rest of the relative code below. Can anybody please help me present my UIAlerController on my SKScene.
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"You Lose!" message:@"Do You Want To Beat This Level?" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *CancelButton = [UIAlertAction actionWithTitle:@"GiveUp" style:UIAlertControllerStyleAlert handler:<#^(UIAlertAction *action)handler#>]
The SKScene
instance can't invoke presentViewController(_:animated:completion)
because it is not a subclass of UIViewController
. However, if you rewrite as such, your alert will launch:
self.view?.window?.rootViewController?.presentViewController(alert, animated: true, completion: nil)
ps: there will be a warning though that Attempt to present <UIAlertController: 0x7fc31eb32e50> on <Sample_Game.GameViewController: 0x7fc31bd9b4f0> which is already presenting
. If anyone knows how to eradicate this warning, that will be great.
[Updated 11 August 2016]
To eradicate the aforementioned warning, check if the rootViewController has presented a view controller:
let vc = self.view?.window?.rootViewController
if vc.presentedViewController == nil {
vc.presentViewController(alert, animated: true, completion: nil)
}
SKScene shouldn't be the one presenting the UIAlertController, but rather a UIViewController such as your initial GameViewController. Above code works fine when called from a UIViewController.
You could use NSNotificationCenter to help you call your view controller.
Add this to your view controller's viewDidLoad method,
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerLost:)
name:@"PlayerLostNotification"
object:nil];
and you will need to define this method too.
- (void)playerLost:(NSNotification*) notification {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"You Lose!"
message:@"Do You Want To Beat This Level?"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* cancel = [UIAlertAction actionWithTitle:@"GiveUp"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:cancel];
[self presentViewController:alert animated:YES completion:nil];
}
In your SKScene when the player loses,
[[NSNotificationCenter defaultCenter] postNotificationName:@"PlayerLostNotification" object:self];
Just set a pointer to your viewController when you create your scene. Then you can call it like this:
[self.viewController presentViewController:alert animated:YES completion:nil];
In your ViewController:
// Create and configure the scene.
GameScene *scene = [GameScene sceneWithSize:viewSize];
SKView * skView = (SKView *)self.view;
scene.viewController = self;
// Present the scene.
[skView presentScene:scene];