When to use didMoveToView or initWithSize with SpriteKit in xCode 6.4

Since xCode has been upgraded to version 6.0, the default method for SpriteKit in "GameScene" (the default script) is changed to:

-(void) didMoveToView:(SKView *) view { /* Scene set up in here */ } 

unlike the older method:

 -(id) initWithSize:(CGSize) size { if (self = [super initWithSize:size]{ /* Scene set up in here */ } } 

I understand that the new method (as with the changes in the view controller) is used to control imports from the .sks file, which is new in xCode 6. However, I was curious if I wanted to use the new β€œstoryboard” format, which is the file .sks should I use the new method? Or should I change the method back to the initWithSize method and just delete the .sks file?

+5
source share
3 answers

Init methods should be used for initialization, but keep in mind that inside init, view is always nil . Thus, any code that needs a view must be ported to the didMoveToView method (it is called immediately after the scene is presented by the view).

About initWithSize in Xcode 6 ... By default, a scene is loaded from a .sks file. Because of this, initWithSize never really called. Instead, initWithCoder is called:

 - (instancetype)initWithCoder:(NSCoder *)aDecoder { if (self = [super initWithCoder:aDecoder]) { // do stuff } return self; } 

Thus, initializing anything inside initWithSize will have no effect. If you decide to delete the .sks file and create the scene in the β€œold” way, you can do something like this in a view controller:

 - (void)viewDidLoad { [super viewDidLoad]; // Configure the view. SKView * skView = (SKView *)self.view; skView.showsFPS = YES; skView.showsNodeCount = YES; /* Sprite Kit applies additional optimizations to improve rendering performance */ skView.ignoresSiblingOrder = YES; // Create and configure the scene. GameScene *scene = [GameScene sceneWithSize:self.view.bounds.size]; scene.scaleMode = SKSceneScaleModeAspectFill; // Present the scene. [skView presentScene:scene]; } 

After that, you can use initWithSize to initialize.

Note that in viewDidLoad, the final size of the view is not yet known, and using viewWillLayoutSubviews instead may be the right choice. More details here .

And the correct implementation of viewWillLayoutSubviews for the purpose of initializing the scene:

 - (void)viewWillLayoutSubviews { [super viewWillLayoutSubviews]; // Configure the view. SKView * skView = (SKView *)self.view; skView.showsFPS = YES; skView.showsNodeCount = YES; /* Sprite Kit applies additional optimizations to improve rendering performance */ skView.ignoresSiblingOrder = YES; //viewWillLayoutSubviews can be called multiple times (read about this in docs ) so we have to check if the scene is already created if(!skView.scene){ // Create and configure the scene. GameScene *scene = [GameScene sceneWithSize:self.view.bounds.size]; scene.scaleMode = SKSceneScaleModeAspectFill; // Present the scene. [skView presentScene:scene]; } } 

Quick code:

 override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene { // Configure the view. let skView = self.view as SKView skView.showsFPS = true skView.showsNodeCount = true skView.showsPhysics = true skView.showsDrawCount = true /* Sprite Kit applies additional optimizations to improve rendering performance */ skView.ignoresSiblingOrder = true /* Set the scale mode to scale to fit the window */ if(skView.scene == nil){ scene.scaleMode = .AspectFill scene.size = skView.bounds.size skView.presentScene(scene) } } } 
+5
source

I think that in all senses and purposes, the difference between the two methods is small when it comes to the actual setup of your scene and its use. ( initWithSize is called when the scene is initialized, and didMoveToView always called right when the scene is represented by the view). I think if you really want to see the initialization, you can just use the init method without any problems.

Regarding the .sks file:

take a look at the view controller implementation file. Right above the v.controller methods you will see:

 @implementation SKScene (Unarchive) + (instancetype)unarchiveFromFile:(NSString *)file { /* Retrieve scene file path from the application bundle */ NSString *nodePath = [[NSBundle mainBundle] pathForResource:fileofType:@"sks"]; /* Unarchive the file to an SKScene object */ NSData *data = [NSData dataWithContentsOfFile:nodePath options:NSDataReadingMappedIfSafe error:nil]; NSKeyedUnarchiver *arch = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; [arch setClass:self forClassName:@"SKScene"]; SKScene *scene = [arch decodeObjectForKey:NSKeyedArchiveRootObjectKey]; [arch finishDecoding]; return scene; } @end 

This is the part that handles sks. Using a file is completely optional, you are not forced to do this, and it really does not affect the setting of your scene. However, if you want to work with it, you will find that you will need to work with this piece of code.

+2
source

Both options are correct. It is said that the init method does not actually coincide with the didMoveToView: method, since this last one will be called as soon as SKScene is presented in SKView .

0
source

All Articles