Search code examples
iosobjective-csprite-kitskscene

Passing Data to SKScene from UIVIewController


What I am trying to accomplish is (should be at least..) very simple: I want to present an SKScene with data that I have in the UIViewController that is presenting this scene. In other words, I have a variable chapter declared as the following:

#import <UIKit/UIKit.h>
#import <SpriteKit/SpriteKit.h>

@interface ViewController : UIViewController

@property (nonatomic) NSInteger chapter;

@end

I have tested with logs that the variable chapter is in fact declared (in my case i am just testing with it as 4).

Here is my ViewController.m file and how I am presenting my scene:

- (void)viewDidLoad {
    [super viewDidLoad];
    .
    .
    .
    // Configure the view.
    SKView *skView = (SKView *)self.view;

    if (!skView.scene) {
        skView.showsFPS = YES;
        skView.showsNodeCount = YES;

        // Create and configure the scene.
        scene = [OLevel sceneWithSize:CGSizeMake(skView.bounds.size.width, skView.bounds.size.height)];
        scene.scaleMode = SKSceneScaleModeResizeFill;

        // Set the SKScene chapter #
        scene.chapter = self.chapter;     // <<<< NOT WORKING?
        NSLog(@"CHAP TO PASS: %u", self.chapter);
        NSLog(@"CHAP RECEIVED: %u", scene.chapter);

        // Present the scene.
        [skView presentScene:scene];

}

With scene defined as the following, with the viewDidLoad being the one shown above: (I have it subclassed)

@interface ViewController () {
    OLevel *scene;
}

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    .
    .
    .

Here is my OLevel.h class:

#import <SpriteKit/SpriteKit.h>
#import <GameplayKit/GameplayKit.h>

@interface OLevel : SKScene <SKPhysicsContactDelegate, GKAgentDelegate>

@property (nonatomic) NSInteger chapter;

@end

And my OLevel.m*:

- (id)initWithSize:(CGSize)size {

    if (self = [super initWithSize:size]) {
        NSLog(@"Creating scene");

        NSLog(@"CHAP: %u", self.chapter);

        [self setUpScene];       
    }

    return self;
}

I am very much confused as to why this approach is not working. I have set the property in my ViewController to the desired chapter value, I have then told my Olevel what value it is and to set it's own chapter property to such value, and then present the scene correctly. Why do I continue to get 0??

2016-07-18 23:52:32.189 TESTAPP[2038:684620] CHAP TO PASS: 4
2016-07-18 23:52:32.193 TESTAPP[2038:684620] CHAP RECEIVED: 0
2016-07-18 23:52:32.195 TESTAPP[2038:684620] Creating scene
2016-07-18 23:52:32.195 TESTAPP[2038:684620] CHAP: 0

I know this question has been answered here with the same approach that I had originally used before looking for an answer, but I have yet to get it to work..

If anyone knows what I am doing wrong please help me.


Solution

  • You have initialize your scene with the wrong syntax, without type:

    ...      
    // Create and configure the scene.
    OLevel *scene = [OLevel sceneWithSize:CGSizeMake(skView.bounds.size.width, skView.bounds.size.height)];
    scene.scaleMode = SKSceneScaleModeResizeFill;
    
    // Set the SKScene chapter #
    scene.chapter = self.chapter; 
    ...
    

    If you want you can also subclass init method with chapter

    OLevel.h:

    @interface GameScene : SKScene <SKPhysicsContactDelegate, GKAgentDelegate>
    
    @property (nonatomic) NSInteger chapter;
    
    -(id)initWithSize:(CGSize)size chapter:(NSInteger)chapter;
    +(id)sceneWithSize:(CGSize)size chapter:(NSInteger)chapter;
    
    @end
    

    OLevel.m:

    #import "GameScene.h"
    @implementation GameScene
    
        -(id)initWithSize:(CGSize)size chapter:(NSInteger)chapter {
    
         if (self = [super initWithSize:size]) {
            self.chapter = chapter;
            //some custom code here
            NSLog(@"Creating scene");
            NSLog(@"CHAP: %ld", (long)self.chapter);
    
         }
         return self;
        }
    
        +(id)sceneWithSize:(CGSize)size chapter:(NSInteger)chapter {
              return ((GameScene *)[[self alloc] initWithSize:size chapter:chapter]);
        }
    
        -(void)didMoveToView:(SKView *)view { 
          ...
        }
    }
    

    In this case you can create your scene as:

       // Create and configure the scene.
        scene = [OLevel sceneWithSize:CGSizeMake(skView.bounds.size.width, skView.bounds.size.height) chapter:self.chapter];
        scene.scaleMode = SKSceneScaleModeResizeFill;