Garry Garry - 4 months ago 21
Swift Question

How do you rename the default scene in the iOS SpriteKit template?

I'm very new to both Swift and iOS development.

I have been working on a game based off Apple's SpriteKit (with GameplayKit integration) template.

All was working fine until I renamed GameScene.swift and GameScene.sks to MapMainScene.swift and MapMainScene.sks. I made sure to change this code in GameViewController.swift:

override func viewDidLoad() {
super.viewDidLoad()

// Load 'GameScene.sks' as a GKScene. This provides gameplay related content
// including entities and graphs.
if let scene = GKScene(fileNamed: "GameScene") {

// Get the SKScene from the loaded GKScene
if let sceneNode = scene.rootNode as! GameScene? {

// Copy gameplay related content over to the scene
sceneNode.entities = scene.entities
sceneNode.graphs = scene.graphs

// Set the scale mode to scale to fit the window
sceneNode.scaleMode = .aspectFill

// Present the scene
if let view = self.view as! SKView? {
view.presentScene(sceneNode)

view.ignoresSiblingOrder = true

view.showsFPS = true
view.showsNodeCount = true
}
}
}
}


to:

override func viewDidLoad() {
super.viewDidLoad()

// Load 'MainMapScene.sks' as a GKScene. This provides gameplay related content
// including entities and graphs.
if let scene = GKScene(fileNamed: "MainMapScene") {

// Get the SKScene from the loaded GKScene
if let sceneNode = scene.rootNode as! MainMapScene? {

// Copy gameplay related content over to the scene
sceneNode.entities = scene.entities
sceneNode.graphs = scene.graphs

// Set the scale mode to scale to fit the window
sceneNode.scaleMode = .aspectFill

// Present the scene
if let view = self.view as! SKView? {
view.presentScene(sceneNode)

view.ignoresSiblingOrder = true

view.showsFPS = true
view.showsNodeCount = true
}
}
}
}


I also changed the following in
Gamescene.swift
:

class GameScene: SKScene {
// Some code
}


to this in
MainMapScene.swift
:

class MainMapScene: SKScene {
// Some code
}


but the app crashes upon launch. The output of the console says:

2016-07-21 16:29:35.593592 MyGame[10656:1944648] [User Defaults] CFPrefsPlistSource<0x6080000e5e00> (Domain: kCFPreferencesAnyApplication, User: kCFPreferencesCurrentUser, ByHost: No, Container: (null)) is waiting for writes to complete so it can determine if new data is available
2016-07-21 16:29:35.603729 MyGame[10656:1944648] [FenceWorkspace] creating a CA fence port (5d13)
2016-07-21 16:29:35.638 MyGame[10656:1944648] *** Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: '*** -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (GameScene) for key (root); the class may be defined in source code or a library that is not linked'
*** First throw call stack:


So it looks like there is still a reference to
GameScene
somewhere in my project but I have done a project-wide search and there is no
GameScene
anywhere to be found.

I'm sure this is something really straightforwards. Do I need to change an outlet or something in the storyboard editor?? I can reproduce this problem by trying to change the name of
GameScene
in a new project too so I know it's not something specific to my project.

Answer

GameScene is actually referenced in one more place, and the error coming from NSKeyedArchiver should clue you in as to where: it's encoded in the .sks file you're loading. You can find it in the "Custom Class" tab of the .sks file in Xcode's editor.

Custom Class Tab

This setting tells NSKeyedUnarchiver what class the encoded scene should be when you load the .sks file. This should be the last remaining reference to GameScene, so this should complete your renaming!