Question

I have two UIViewControllers. The user starts with UIViewController. Then the user clicks on a button to play a game. So the application seque-switches to the other viewcontroller, PlayViewController, which shows the game play with SKView. And ActionScene is an SKScene subclass that is responsible for the game play. When the user fails, the application will display a label (SKLabelNode) and ask if he or she wants to quit the game. If the user taps this label, the gamer will be brought back to the main view controller (UIViewController) via PlayViewController. So I figure that ActionScene should delegate this task to PlayViewController. The following comes from ActionScene.

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

@protocol actionDelegate;
@interface ActionScene : SKScene

@property (weak) id <actionDelegate> delegate;
@end

@protocol actionDelegate <NSObject>
@required

// Delegate
- (void)closeScene;
@end

// ActionScene.m
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    for (UITouch *touch in touches) {
    SKNode *n = [self nodeAtPoint:[touch locationInNode:self]];
        if (n != self && [n.name isEqual: @"doneLabel"]) { // It was else if before.  I've made a change.
            [[self childNodeWithName:@"doneLabel"] removeFromParent]; // The user chooses to end the game by tapping doneLabel (SKLabelNode)
            [self.delegate closeScene];
        }
    }
}

As for PlayViewController, it's responsible for presenting ActionScene to SKView and also sending the user back to UIViewController as follows.

// PlayViewController.h
#import "ActionScene.h"

@interface PlayViewController : UIViewController <actionDelegate>
@property (strong,nonatomic) ActionScene *actionScene;

@end

// PlayViewController.m
- (void)viewWillLayoutSubviews {
    SKView *spriteView = [[SKView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:spriteView];

    SKScene *scene = [[ActionScene alloc] initWithSize:spriteView.frame.size];
    [self.actionScene setDelegate:self]; // Letting ActionScene delegate a task to itself
    [spriteView presentScene:scene];
}

- (void)closeScene {
    // It doesn't get a call from ActionScene
}

So when the user taps the done label, closeScene is designed to kick in. But this delegate method never gets a call. I haven't developed an iOS application for the past 9 months. But I think I have the right idea. What am I doing wrong? So far, I've read this topic, this topic and others.

Thank you for your help.

// Additional explainations //

  1. All actions are removed before the user gets to tap doneLabel.
  2. The game application will enter touchBegan. Yet, it'll skip the [spriteView presentScene:scene] line.
Was it helpful?

Solution 2

In reference to this post, my desperate measure has worked out. The following change is made to the PlayViewController.m to bring the user back to UIViewController.

- (void)viewWillLayoutSubviews {
    SKView *spriteView = [[SKView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:spriteView];

    SKScene *scene = [[ActionScene alloc] initWithSize:spriteView.frame.size];
    [self.actionScene setDelegate:self]; // Letting ActionScene delegate a task to itself
    [spriteView presentScene:scene];
}

to

- (void)viewWillLayoutSubviews {        
    SKView *spriteView = [[SKView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:spriteView];

    ActionScene *scene = [ActionScene sceneWithSize:spriteView.bounds.size];
    [scene setDelegate:self];
    [spriteView presentScene:scene];
}

Now, I can move on with my game development at full pace without a major worry.

OTHER TIPS

I implemented your code and everything works like a charm. Set a breakpoint on a line:

[self.delegate closeScene];

to see if it gets called.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top