Presenting a Uiviewcontroller from Skscene Shows Black Screen

Presenting a UIViewController from SKScene shows black screen

To present a SKScene from another SKScene you should do for example :

let nextScene = MainScene(size: self.scene!.size)
self.scene?.view?.presentScene(nextScene, transition: SKTransition.doorway(withDuration: 1))

You don't need to retrieve your currentViewController because you have always access to the view of your scene


As explained to the comments below, there are various methods to call a function implemented to your game viewController, one could be to create a delegate/protocol as showed in this code:

GameScene example:

import SpriteKit
protocol GameViewControllerDelegate: class {
func callMethod(inputProperty:String)
}
class GameScene: SKScene {
weak var gameViewControllerDelegate:GameViewControllerDelegate?
override func didMove(to view: SKView) {
gameViewControllerDelegate?.callMethod(inputProperty: "call game view controller method")
}
}

GameViewController example:

class GameViewController: UIViewController, GameViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
// Load the SKScene from 'GameScene.sks'
if let scene = SKScene(fileNamed: "GameScene") {
let gameScene = scene as! GameScene
gameScene.gameViewControllerDelegate = self
gameScene.scaleMode = .aspectFill
view.presentScene(gameScene)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
func callMethod(inputProperty:String) {
print("inputProperty is: ",inputProperty)
}
}

Output:

Sample Image

New SKScene Set as Default in SpriteKit Game Turns Out Blank

If you have a corresponding SKS file created in the Scene editor then you load your scene like so...

// Load the SKScene from WelcomeScene.sks'
if let welcomeScene = WelcomeScene(fileNamed: "WelcomeScene") {
welcomeScene.scaleMode = .aspectFill
view.presentScene(welcomeScene)
}

if you do not have a corresponding SKS file created in the scene editor but would rather load the scene that was created in code use...

welcomeScene= WelcomeScene(size: skView.bounds.size)
welcomeScene.scaleMode = .aspectFill
skView.presentScene(welcomeScene)

Xcode 11.5 IOS 13.5 Dark screen after setting view controller in Scenedelgate

This line is wrong:

self.view?.window?.rootViewController = UINavigationController(rootViewController: HomeViewController())

The problem, in particular, is this phrase in your code:

HomeViewController()

That creates a new blank HomeViewController, not the instance you designed in the storyboard. To get that instance, tell the storyboard to instantiate it for you.

Presenting a UIViewController from an SKscene (SpriteKit)

You cannot move directly from an SKScene to another UIViewController.

However, the SKScene is already contained in a UIViewController.

You can use delegation to pass a method call from the scene to its controller. The controller can then move to another view controller.

So...

  1. Create a delegate protocol that contains a method something like... - (void)transitionToOtherViewController;

  2. Set the current view controller as the delegate of your scene.

    self.scene.delegate = self;

  3. When you want to move to another view controller. In the scene you would have something like...

    [self.delegate transitionToOtherViewController];

Then in the view controller you have...

- (void)transitionToOtherViewController
{
MyOtherViewController *controller = [MyOtherViewController new];

[self.navigationController pushViewController:controller animated:YES];
}

Or something like this...

Losing reference to GameViewController from inside SpriteKit when moving between scenes - want to move between SKScene and UITableView

There are two simple methods to call a GameViewController function from other classes: through a delegate or by making the class instance static.

// DELEGATE
//
// GameViewController.swift

protocol GameView_Delegate
{
func show_ui()
}

class GameViewController: UIViewController, GameView_Delegate
{
override func viewDidLoad()
{

// ...

if let view = self.view as! SKView?
{
if let scene = SKScene(fileNamed: "MenuScene")
{
scene.scaleMode = .aspectFill

// pass GameViewController reference
scene.gv_delegate = self
}

view.presentScene(scene)
}

// ...

}

func show_ui()
{
// show ui
// ...
}
}

// MenuScene.swift

class MenuScene: SKScene
{
var gv_delegate : GameView_Delegate!

func settings()
{
// call function show_ui from GameViewController
gv_delegate.show_ui()
}

func game_scene()
{
let transition = SKTransition.fade(with: UIColor.white, duration: 1.0)
let next_scene = GameScene()
next_scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
next_scene.scaleMode = self.scaleMode
next_scene.size = self.size

// before moving to next scene, we must pass the delegate, so we
// don't lose the connection with the GameViewController
next_scene.gv_delegate = gv_delegate
self.view?.presentScene(next_scene, transition: transition)
}
}

// GameScene.swift

class GameScene: SKScene
{
var gv_delegate : GameView_Delegate!

func settings()
{
// call function show_ui from GameViewController
gv_delegate.show_ui()
}

func main_scene()
{
let transition = SKTransition.fade(with: UIColor.white, duration: 1.0)
let next_scene = MainScene()
next_scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
next_scene.scaleMode = self.scaleMode
next_scene.size = self.size

// before moving to next scene, we must pass the delegate, so we
// don't lose the connection with the GameViewController
next_scene.gv_delegate = gv_delegate
self.view?.presentScene(next_scene, transition: transition)
}
}

When you enter a new scene, for example GameScene, the old scene MainScene in our case is deallocated (all variables emptied, all references destroyed) and a new GameScene instance is created and displayed on screen. If afterwards you want to exit that scene and enter MainScene, a new instance of that class will be created with the GameViewController reference empty. We should reference it again or pass the reference before exiting the scene (as in my example).

// STATIC
//
// GameViewController.swift

class GameViewController: UIViewController
{
static var shared : GameViewController!

override func viewDidLoad()
{
super.viewDidLoad()

GameViewController.shared = self

// ...

}

func show_ui()
{
// show ui
// ...
}
}

// MenuScene.swift

class MenuScene: SKScene
{
func settings()
{
// call function show_ui from GameViewController

GameViewController.shared.show_ui()
}
}

Read pros/cons of each method and chose the one that suits your app the best. Also, avoid using UIKit inside SpriteKit.

Present another View Controller from SkScene

I assume by your question that you are looking to do some social media posting.

You can either pass a reference for your View Controller to your SKScene or you can use NSNotificationCenter instead. I prefer to use the latter.

First make sure you have added the Social.framework to your project.

Import the social framework into your View Controller #import <Social/Social.h>

Then in your View Controller's viewDidLoad method add this code:

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(createTweet:)
name:@"CreateTweet"
object:nil];

Next add this method to your View Controller:

-(void)createTweet:(NSNotification *)notification
{
NSDictionary *tweetData = [notification userInfo];
NSString *tweetText = (NSString *)[tweetData objectForKey:@"tweetText"];
NSLog(@"%@",tweetText);

// build your tweet, facebook, etc...
SLComposeViewController *mySLComposerSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter];
[self presentViewController:mySLComposerSheet animated:YES completion:nil];
}

At the appropriate location in your SKScene, (won game, lost game, etc...) add this code:

NSString *tweetText = @"I just beat the last level.";
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:tweetText forKey:@"tweetText"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"CreateTweet" object:self userInfo:userInfo];

The above code sends a NSNotification, with text, which your View Controller will pick up and execute the specified method (which is createTweet in the above example).



Related Topics



Leave a reply



Submit