Presenting UIViewController from SKScene
Solution 1:
Don't try to present UIViewController
from SKScene
directly, this breaks MVC pattern. SKScene
is part of View
, View
should not know anything about ViewController
.
Instead, you can use NSNotificationCenter
to notify SKScene
's UIViewController
that it should present another UIViewController
:
In SKScene
's UIViewController
:
- (void)awakeFromNib {
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(goToGameOverViewController:)
name:@"GoToGameOverViewController"
object:nil];
}
.
-(void)goToGameOverViewController:(NSNotification *) notification {
// Perform a segue or present ViewController directly
//[self performSegueWithIdentifier:@"GameOverSegue" sender:self];
HelpViewController *helpVC = [[HelpViewController alloc]initWithNibName:@"HelpViewController" bundle:nil];
[self presentViewController:helpVC animated: YES completion:nil];
}
.
- (void) dealloc
{
// If you don't remove yourself as an observer, the Notification Center
// will continue to try and send notification objects to the deallocated
// object.
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
In SKScene
:
- (void)gameOver {
[[NSNotificationCenter defaultCenter]
postNotificationName:@"GoToGameOverViewController" object:self];
}
Solution 2:
Your problem is twofold:
Casting a
UIViewController
toSKScene
.SKScene *sks = (SKScene*)helpVC;
Casting should be done in other scenarios : e.g. between primitives, between UI Foundation and CF classes or between a subclass and it's super (but shouldn't be done in the opposite way!).
Long story short - not in this scenario (these classes have nothing in common)You ask your view to present a scene, but pass a viewController instead :
[self.view presentScene:sks];
So, what happened here ?presentScene:
thinks they got an SKScene object, thus sends some message tosks
. A message thatsks
does not understand... and crashes.
How to solve this ?
Grab your presenting view controller.
Either in a global, or just grab your root view controller from the app delegate:
UIViewController *rootVC = [UIApplication sharedApplication].keyWindow.rootViewController;
[rootVC presentViewController:yourPresentedVC animated:YES completion:nil];
In case you're using a tab bar/navigation controller you should grab their presented VC.