转换到 SpriteKit 中的另一个 SKScene 后解除分配 SKScene [英] Deallocate SKScene after transition to another SKScene in SpriteKit

查看:19
本文介绍了转换到 SpriteKit 中的另一个 SKScene 后解除分配 SKScene的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个视图控制器,它有三个子场景.

I have a view controller that has three skscenes as children.

当我从一个过渡到另一个时,旧的 skscene 不会被释放.

When I transition from one to another, the old skscene doesn't get deallocated.

我希望它被释放,就好像它从未存在过一样.

I want it to get deallocated as if it was never there.

例子:

当我第一次加载应用程序时,只有 1 个 skscene 可见(比如说它占用 100mb 内存),然后我转换到另一个(100mb 以上),然后是第三个(300mb 内存).

When I first load the app, only 1 skscene is visible (say it takes up 100mb memory), then I transition to another (100mb more), and then the third (300mb memory).

我最终会拥有 300mb 内存,并且我想一直拥有 100 块.

I would end up with 300mb memory and I want to have 100 at all times.

我怎样才能做到这一点?

How can I achieve this?

My view controller: 

//
//  ViewController.m
//  Paddle Jumper
//
//  Created by Chance Daniel on 1/18/14.
//  Copyright (c) 2014 Max Hudson. All rights reserved.
//

#import "Flurry.h"
#import "ViewController.h"
#import "startViewController.h"

@implementation ViewController{
    BOOL sceneSetUp;
}

- (void)viewWillLayoutSubviews
{
    if(!sceneSetUp){

        [super viewWillLayoutSubviews];

        // Configure the view.
        SKView * skView = (SKView *)self.view;
        //skView.showsFPS = YES;
        //skView.showsNodeCount = YES;

        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        if([[defaults objectForKey:@"firstTime"] intValue] != 1){
            [defaults setObject:[NSNumber numberWithInt:1] forKey:@"firstTime"];

            [defaults setObject:@"ggr" forKey:@"skinSelected"];
            [defaults setObject:[NSNumber numberWithInt:2] forKey:@"ggrOwned"];

            [defaults setObject:[NSNumber numberWithInt:5000] forKey:@"gona"];
            [defaults setObject:[NSNumber numberWithInt:1500] forKey:@"points"];
            [defaults setObject:[NSNumber numberWithInt:7] forKey:@"livesLeftValue"];
            [defaults setObject:[NSNumber numberWithInt:3] forKey:@"shieldsLeftValue"];
            [defaults setObject:[NSNumber numberWithInt:2] forKey:@"lvlTwoLeftValue"];
            [defaults setObject:[NSNumber numberWithInt:0] forKey:@"lvlThreeLeftValue"];
        }

        if(![defaults objectForKey:@"tut_game1"]){
            [defaults setObject:[NSNumber numberWithInt:1] forKey:@"tut_game1"];
            [defaults setObject:[NSNumber numberWithInt:1] forKey:@"tut_store"];
            [defaults setObject:[NSNumber numberWithInt:1] forKey:@"tut_daily"];
        }

        [defaults synchronize];

        // Create and configure the scene.
        SKScene * startScene = [StartViewController sceneWithSize:skView.bounds.size];
        startScene.scaleMode = SKSceneScaleModeAspectFill;

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

        sceneSetUp = YES;
    }

}

-(void) switchScene{

}

- (BOOL)shouldAutorotate
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        return UIInterfaceOrientationMaskAllButUpsideDown;
    } else {
        return UIInterfaceOrientationMaskAll;
    }
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}

@end

An SKScene that won't release: //
//  SettingsSKScene.m
//  Paddle Jumper
//
//  Created by Max Hudson on 3/15/14.
//  Copyright (c) 2014 Max Hudson. All rights reserved.
//

#import "SettingsSKScene.h"
#import "gameViewController.h"
#import "StoreScene.h"

@interface SettingsSKScene (){
    SKSpriteNode *bg;
    SKSpriteNode *masterOverlay;
    SKSpriteNode *wbox;
    SKSpriteNode *gamecenter;
    SKSpriteNode *max;
    SKSpriteNode *chance;
    SKSpriteNode *bryce;
    SKSpriteNode *home;
    SKSpriteNode *play;

    SKSpriteNode *chance_link;
    SKSpriteNode *max_link;
    SKSpriteNode *bryce_link;

    SKSpriteNode *fbButton;
    SKSpriteNode *fbToggleYes;
    SKSpriteNode *fbToggleNo;

    SKLabelNode *story1;
    SKLabelNode *story2;
    SKLabelNode *story3;

    SKLabelNode *chance_name;
    SKLabelNode *max_name;
    SKLabelNode *bryce_name;

    SKLabelNode *chance_role;
    SKLabelNode *max_role;
    SKLabelNode *bryce_role;

    SKLabelNode *chance_handle;
    SKLabelNode *max_handle;
    SKLabelNode *bryce_handle;

    SKTexture *bg_texture;
    SKTexture *gamecenter_texture;
    SKTexture *wbox_texture;
    SKTexture *max_texture;
    SKTexture *chance_texture;
    SKTexture *bryce_texture;
    SKTexture *home_texture;
    SKTexture *play_texture;
    SKTexture *fb_texture;
    SKTexture *toggle_yes_texture;
    SKTexture *toggle_no_texture;
}

@end

@implementation SettingsSKScene

-(id) initWithSize:(CGSize)size{
    if(self = [super initWithSize:size]){
        masterOverlay = [SKSpriteNode spriteNodeWithColor:[SKColor blackColor] size:self.frame.size];
        masterOverlay.position = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
        [self addChild:masterOverlay];

        bg_texture = [SKTexture textureWithImageNamed:@"settings_bg"];
        wbox_texture = [SKTexture textureWithImageNamed:@"white_rect_bg"];
        gamecenter_texture = [SKTexture textureWithImageNamed:@"gc"];
        max_texture = [SKTexture textureWithImageNamed:@"max"];
        chance_texture = [SKTexture textureWithImageNamed:@"chance"];
        bryce_texture = [SKTexture textureWithImageNamed:@"bryce"];
        home_texture = [SKTexture textureWithImageNamed:@"home_light"];
        play_texture = [SKTexture textureWithImageNamed:@"play_light"];
        fb_texture = [SKTexture textureWithImageNamed:@"fb_light"];
        toggle_yes_texture = [SKTexture textureWithImageNamed:@"toggle_yes"];
        toggle_no_texture = [SKTexture textureWithImageNamed:@"toggle_no"];

        NSArray *to_preload = @[bg_texture, wbox_texture, gamecenter_texture, max_texture, chance_texture, bryce_texture, home_texture, play_texture, fb_texture, toggle_yes_texture, toggle_no_texture];

        [SKTexture preloadTextures:to_preload withCompletionHandler:^{
            [self fadeRemove:masterOverlay];
            [self initialize];
        }];
    }
    return self;
}

-(void) fadeRemove: (SKNode *) node{
    double duration = arc4random() % 10;
    duration *= 0.05;
    SKAction *fadeOut = [SKAction fadeOutWithDuration:0.1+duration];
    SKAction *remove = [SKAction runBlock:^{
        [node removeFromParent];
    }];

    [node runAction:[SKAction sequence:@[fadeOut, remove]]];
}

-(void) initialize{
    bg = [SKSpriteNode spriteNodeWithTexture:bg_texture];
    bg.position = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
    bg.zPosition = 0;

    wbox = [SKSpriteNode spriteNodeWithTexture:wbox_texture];
    wbox.position = CGPointMake(self.frame.size.width/2, 70);
    wbox.alpha = 0.8;
    wbox.zPosition = 2;

    gamecenter = [SKSpriteNode spriteNodeWithTexture:gamecenter_texture];
    gamecenter.position = CGPointMake(self.frame.size.width/2 + 100, self.frame.size.height/2-2);
    gamecenter.name = @"gc";
    gamecenter.zPosition = 2;

    fbButton = [SKSpriteNode spriteNodeWithTexture:fb_texture];
    fbButton.size = CGSizeMake(36, 36);
    fbButton.position = CGPointMake(self.frame.size.width/2 - 115, self.frame.size.height/2-2);
    fbButton.name = @"fb";
    fbButton.zPosition = 2;

    fbToggleNo = [SKSpriteNode spriteNodeWithTexture:toggle_no_texture];
    fbToggleNo.position = CGPointMake(self.frame.size.width/2 - 50, self.frame.size.height/2-2);
    fbToggleNo.size = CGSizeMake(fbToggleNo.size.width/3, fbToggleNo.size.height/3);
    fbToggleNo.name = @"fbno";
    fbToggleNo.zPosition = 2;

    fbToggleYes = [SKSpriteNode spriteNodeWithTexture:toggle_yes_texture];
    fbToggleYes.position = CGPointMake(self.frame.size.width/2 - 70, self.frame.size.height/2-2);
    fbToggleYes.name = @"fbyes";
    fbToggleYes.zPosition = 2;

    int hpBuffer = 40;
    int hpZ = 2;

    home = [SKSpriteNode spriteNodeWithTexture:home_texture];
    home.position = CGPointMake(hpBuffer, self.frame.size.height - hpBuffer);
    home.zPosition = hpZ;
    home.name = @"home";

    play = [SKSpriteNode spriteNodeWithTexture:play_texture];
    play.position = CGPointMake(self.frame.size.width - hpBuffer, self.frame.size.height - hpBuffer);
    play.zPosition = hpZ;
    play.name = @"play";

    [self addChild:bg];
    [self addChild:wbox];
    [self addChild:gamecenter];
    [self addChild:home];
    [self addChild:play];

    [self addChild:fbButton];
    [self addChild:fbToggleNo];

    [self addCredits];
    [self addStory];
}

-(void) addCredits{
    /* images */

    int cmbZ = wbox.zPosition + 1;
    int cmbY = wbox.position.y;
    int cmbXUnit = 132;
    int cmbX = self.frame.size.width/2 - (3*cmbXUnit)/2 + 20;
    int cmbWidth = 40;

    chance  = [SKSpriteNode spriteNodeWithTexture:chance_texture];
    max = [SKSpriteNode spriteNodeWithTexture:max_texture];
    bryce  = [SKSpriteNode spriteNodeWithTexture:bryce_texture];

    chance.zPosition = cmbZ;
    max.zPosition = cmbZ;
    bryce.zPosition = cmbZ;

    chance.position = CGPointMake(cmbX+cmbXUnit*0, cmbY+3);
    max.position = CGPointMake(cmbX+cmbXUnit*1 + 10, cmbY);
    bryce.position = CGPointMake(cmbX+cmbXUnit*2 + 10, cmbY+5);

    chance.size = CGSizeMake(cmbWidth, (chance.size.height/chance.size.width)*cmbWidth);
    max.size = CGSizeMake(cmbWidth, (max.size.height/max.size.width)*cmbWidth);
    bryce.size = CGSizeMake(cmbWidth, (bryce.size.height/bryce.size.width)*cmbWidth);

    [self addChild:chance];
    [self addChild:max];
    [self addChild:bryce];

    /* names */

    int cmb_nameXUnit = 30;
    int cmb_nameY = wbox.position.y - 10;
    int cmb_nameFontSize = 18;

    chance_name = [SKLabelNode labelNodeWithFontNamed:@"BebasNeue"];
    max_name = [SKLabelNode labelNodeWithFontNamed:@"BebasNeue"];
    bryce_name = [SKLabelNode labelNodeWithFontNamed:@"BebasNeue"];

    chance_name.text = @"Chance Daniel";
    max_name.text = @"Max Hudson";
    bryce_name.text = @"Bryce Daniel";

    chance_name.fontColor = [SKColor blackColor];
    max_name.fontColor = [SKColor blackColor];
    bryce_name.fontColor = [SKColor blackColor];

    chance_name.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeLeft;
    max_name.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeLeft;
    bryce_name.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeLeft;

    chance_name.position = CGPointMake(chance.position.x + cmb_nameXUnit, cmb_nameY);
    max_name.position = CGPointMake(max.position.x + cmb_nameXUnit, cmb_nameY);
    bryce_name.position = CGPointMake(bryce.position.x + cmb_nameXUnit, cmb_nameY);

    chance_name.fontSize = cmb_nameFontSize;
    max_name.fontSize = cmb_nameFontSize;
    bryce_name.fontSize = cmb_nameFontSize;

    chance_name.zPosition = cmbZ;
    max_name.zPosition = cmbZ;
    bryce_name.zPosition = cmbZ;

    [self addChild:chance_name];
    [self addChild:max_name];
    [self addChild:bryce_name];

    /* roles */

    int cmb_roleY = wbox.position.y - 25;
    int cmb_roleFontSize = 11;

    chance_role = [SKLabelNode labelNodeWithFontNamed:@"BebasNeue"];
    max_role = [SKLabelNode labelNodeWithFontNamed:@"BebasNeue"];
    bryce_role = [SKLabelNode labelNodeWithFontNamed:@"BebasNeue"];

    chance_role.text = @"Programmer";
    max_role.text = @"Programmer";
    bryce_role.text = @"Graphic Designer";

    chance_role.fontColor = [SKColor darkGrayColor];
    max_role.fontColor = [SKColor darkGrayColor];
    bryce_role.fontColor = [SKColor darkGrayColor];

    chance_role.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeLeft;
    max_role.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeLeft;
    bryce_role.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeLeft;

    chance_role.position = CGPointMake(chance.position.x + cmb_nameXUnit + 19, cmb_roleY);
    max_role.position = CGPointMake(max.position.x + cmb_nameXUnit + 12, cmb_roleY);
    bryce_role.position = CGPointMake(bryce.position.x + cmb_nameXUnit + 6, cmb_roleY);

    chance_role.fontSize = cmb_roleFontSize;
    max_role.fontSize = cmb_roleFontSize;
    bryce_role.fontSize = cmb_roleFontSize;

    chance_role.zPosition = cmbZ;
    max_role.zPosition = cmbZ;
    bryce_role.zPosition = cmbZ;

    [self addChild:chance_role];
    [self addChild:max_role];
    [self addChild:bryce_role];

    /* twitter handles */

    int cmb_handY = wbox.position.y - 40;
    int cmb_handFontSize = 10;

    chance_handle = [SKLabelNode labelNodeWithFontNamed:@"BebasNeue"];
    max_handle = [SKLabelNode labelNodeWithFontNamed:@"BebasNeue"];
    bryce_handle = [SKLabelNode labelNodeWithFontNamed:@"BebasNeue"];

    chance_handle.text = @"@ChanceOfThat";
    max_handle.text = @"@max_hud";
    bryce_handle.text = @"@BryceOfLife";

    chance_handle.fontColor = [SKColor darkGrayColor];
    max_handle.fontColor = [SKColor darkGrayColor];
    bryce_handle.fontColor = [SKColor darkGrayColor];

    chance_handle.position = CGPointMake(chance.position.x, cmb_handY);
    max_handle.position = CGPointMake(max.position.x, cmb_handY);
    bryce_handle.position = CGPointMake(bryce.position.x, cmb_handY);

    chance_handle.fontSize = cmb_handFontSize;
    max_handle.fontSize = cmb_handFontSize;
    bryce_handle.fontSize = cmb_handFontSize;

    chance_handle.zPosition = cmbZ;
    max_handle.zPosition = cmbZ;
    bryce_handle.zPosition = cmbZ;

    [self addChild:chance_handle];
    [self addChild:max_handle];
    [self addChild:bryce_handle];

    /* touchzones */

    CGSize cmdL_size = CGSizeMake(120, 70);
    SKColor *cmdL_color = [SKColor clearColor];
    int cmdLZ = 3;
    int cmdLX = cmbX + 40;

    chance_link = [SKSpriteNode spriteNodeWithColor:cmdL_color size:cmdL_size];
    max_link = [SKSpriteNode spriteNodeWithColor:cmdL_color size:cmdL_size];
    bryce_link = [SKSpriteNode spriteNodeWithColor:cmdL_color size:cmdL_size];

    chance_link.position = CGPointMake(cmdLX+cmbXUnit*0, cmbY);
    max_link.position = CGPointMake(cmdLX+cmbXUnit*1 + 10, cmbY);
    bryce_link.position = CGPointMake(cmdLX+cmbXUnit*2 + 10, cmbY);

    chance_link.zPosition = cmdLZ;
    max_link.zPosition = cmdLZ;
    bryce_link.zPosition = cmdLZ;

    chance_link.name = @"c_handle";
    max_link.name = @"m_handle";
    bryce_link.name = @"b_handle";

    [self addChild:chance_link];
    [self addChild:max_link];
    [self addChild:bryce_link];
}

-(void) addStory{

    int stX = self.frame.size.width/2;
    int stZ = 2;
    SKColor *stColor = [SKColor whiteColor];

    story1 = [SKLabelNode labelNodeWithFontNamed:@"BebasNeue"];
    story2 = [SKLabelNode labelNodeWithFontNamed:@"BebasNeue"];
    story3 = [SKLabelNode labelNodeWithFontNamed:@"BebasNeue"];

    story1.text = @"Gon";
    story2.text = @"Help Gon-Gon and his friends get";
    story3.text = @"Back to the time they came from!";

    story1.fontColor = stColor;
    story2.fontColor = stColor;
    story3.fontColor = stColor;

    story1.zPosition = stZ;
    story2.zPosition = stZ;
    story3.zPosition = stZ;

    story1.position = CGPointMake(stX, self.frame.size.height - 55);
    story1.fontSize = 50;

    story2.position = CGPointMake(stX, self.frame.size.height - 95);
    story2.fontSize = 30;

    story3.position = CGPointMake(stX, self.frame.size.height - 120);
    story3.fontSize = 20;

    [self addChild:story1];
    [self addChild:story2];
    [self addChild:story3];
}

-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touchUI = [touches anyObject];
    CGPoint touchPoint = [touchUI locationInNode:self];
    SKNode *touchNode = [self nodeAtPoint:touchPoint];

    if([touchNode.name isEqualToString:@"home"]){
        StartViewController *svc = [[StartViewController alloc] initWithSize:self.size];
        SKTransition *fade = [SKTransition fadeWithColor :[SKColor blackColor] duration:0.4];
        [self.view presentScene:svc transition:fade];
    }

    if([touchNode.name isEqualToString:@"play"]){
        gameViewController *gvc = [[gameViewController alloc] initWithSize:self.size];
        SKTransition *fade = [SKTransition fadeWithColor :[SKColor blackColor] duration:0.4];
        [self.view presentScene:gvc transition:fade];
    }

    if([touchNode.name isEqualToString:@"gc"]){
        NSDictionary * dict = [[NSDictionary alloc]initWithObjectsAndKeys:[NSNumber numberWithBool:1], @"showGC", nil];

        [[NSNotificationCenter defaultCenter]postNotificationName:@"kNotificationUpdateBannerView" object:self userInfo:dict];
    }

    if([touchNode.name isEqualToString:@"c_handle"]){
        NSURL *urlApp = [NSURL URLWithString: [NSString stringWithFormat:@"%@", @"twitter:///user?screen_name=ChanceOfThat"]];
        int worked = [[UIApplication sharedApplication] openURL:urlApp];
        if(!worked){
            NSURL *urlApp = [NSURL URLWithString: [NSString stringWithFormat:@"%@", @"https://twitter.com/#!/ChanceOfThat"]];
            [[UIApplication sharedApplication] openURL:urlApp];
        }
    }

    if([touchNode.name isEqualToString:@"m_handle"]){
        NSURL *urlApp = [NSURL URLWithString: [NSString stringWithFormat:@"%@", @"twitter:///user?screen_name=max_hud"]];
        int worked = [[UIApplication sharedApplication] openURL:urlApp];
        if(!worked){
            NSURL *urlApp = [NSURL URLWithString: [NSString stringWithFormat:@"%@", @"https://twitter.com/#!/max_hud"]];
            [[UIApplication sharedApplication] openURL:urlApp];
        }
    }

    if([touchNode.name isEqualToString:@"b_handle"]){
        NSURL *urlApp = [NSURL URLWithString: [NSString stringWithFormat:@"%@", @"twitter:///user?screen_name=BryceOfLife"]];
        int worked = [[UIApplication sharedApplication] openURL:urlApp];
        if(!worked){
            NSURL *urlApp = [NSURL URLWithString: [NSString stringWithFormat:@"%@", @"https://twitter.com/#!/BryceOfLife"]];
            [[UIApplication sharedApplication] openURL:urlApp];
        }
    }
}

@end

推荐答案

提出这个问题的人也遇到了类似的问题 问题.

A similar problem was faced by the person who asked this question.

当被问及他是否能够解决它时,他们说:

When asked whether he was able to solve it, they said:

是的,我做到了,在现场我无能为力或 Sprite Kit,我只需要删除场景并完全从父视图中包含它的视图,切掉它的所有绑定到系统的其他部分,以便记忆也被释放了.

Yes, I did, there wasn't anything I could do about it from the scene or Sprite Kit for that matter, I simply needed to remove the scene and the view containing it completely from the parent view, cut all its bonds to the other parts of the system, in order for the memory to be deallocated as well.

您应该为每个场景使用单独的视图并在这些视图之间进行转换.您可以按照以下步骤使其看起来自然:

You should use separate views for each of your scene and transition between these views. You can follow these steps to make it look natural:

1 - 在您想要从一个场景过渡到另一个场景时,使用以下代码拍摄场景快照:

1 - At the point you want to transition from one scene to the other, take a snapshot of the scene using the following code:

UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, scale);
[self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

然后,将此图像添加为当前场景的SKView的子视图,并移除该场景.

Then, add this image as a subview of the SKView of the current scene, and remove the scene.

2 - 在另一个视图上初始化新场景,并使用 UIView 动画在两个视图之间转换.

2 - Initialise the new scene on another view, and transition between the two views using UIView animation.

3 - 从其父视图中删除第一个视图.

3 - Remove the first view from it's superview.

这篇关于转换到 SpriteKit 中的另一个 SKScene 后解除分配 SKScene的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆