单例不会持久存在于viewcontrollers / spritekit场景中

时间:2014-02-26 01:21:47

标签: ios singleton sprite-kit

这是一款SpriteKit游戏。

我正在使用单身人士来存储整个游戏中可以访问的单个“显示”对象。 'Show'类有一个NSString属性'showTitle'。

在ViewController1中,我设置了单例的“显示”属性。为了测试...然后我从单例中打印出一个'Show'(showTitle)的字符串属性,它正确打印出字符串。

在切换到ViewController2后,我再次从单例中打印出“Show”(showTitle)的相同字符串属性,并再次正确打印字符串。

那么,spritekit场景是从ViewController2初始化的。我尝试打印相同的字符串属性  单例中的“显示”,它打印null而不是字符串。我走得更远,并继续调查ViewController3,试图从单身人士打印showTitle ..... NULL。

为什么我能够访问ViewControllers 1&中单例的'Show'属性? 2,但不是来自精灵套件场景或ViewController3。我哪里错了?

ShowSingleton.h

#import <Foundation/Foundation.h>
#import "Show.h"

@interface ShowSingleton : NSObject

@property (nonatomic, strong) Show* currentShow;

+(ShowSingleton *)singleton;

@end

ShowSingleton.m

#import "ShowSingleton.h"

@implementation ShowSingleton

@synthesize currentShow;

+(ShowSingleton *)singleton {
    static dispatch_once_t pred;
    static ShowSingleton *shared = nil;

    dispatch_once(&pred, ^{
        shared = [[ShowSingleton alloc] init];
    });

    return shared; }

@end

ViewController1:

- (IBAction)openShow:(UIButton*)sender
    {
        //showsarray is an array of 'Show' objects retrieved through core data in another class
        [ShowSingleton singleton].currentShow = [showsarray objectAtIndex:sender.tag];

        NSLog(@"Opened show: %@", [ShowSingleton singleton].currentShow.showTitle);
        //The above line correctly prints the selected showTitle from the singleton
}

在openShow:完成后,segue打开ViewController2。 ViewController2初始化SpriteKit场景。

ViewController2:

- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];

    SKView * skView = (SKView *)self.view;
    if (!skView.scene)
    {
        skView.showsFPS = YES;
        skView.showsNodeCount = YES;
        SKScene * scene = [iMarchMyScene sceneWithSize:skView.bounds.size];
        scene.scaleMode = SKSceneScaleModeAspectFill;
        [skView presentScene:scene];
    }
}

- (void)viewDidLoad
{
    //The following line correctly prints the showTitle from ViewController2
    NSLog(@"processing show: %@", [ShowSingleton singleton].currentShow.showTitle);
}

myScene.m:

-(id)initWithSize:(CGSize)size
{
    if (self = [super initWithSize:size])
    {
        if ([ShowSingleton singleton].currentShow)
        {
            //This always gets called, which tells me the object exists, but null is printed for showTitle
             NSLog(@"show title from scene: %@", [ShowSingleton singleton].currentShow.showTitle);
        }
    }
    return self;
}

2 个答案:

答案 0 :(得分:1)

ShowSingleton *shared的范围是方法,而不是类。

尝试将其声明为AppDelegate的类属性,然后使用以下内容覆盖getter:

@property (strong, nonatomic) Show *currentShow;

然后将getter重写为:

+(Show*)currentShow
{
    static id _currentShow = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        currentShow = [showsarray objectAtIndex:sender.tag]; //probably not this, not sure where in your app flow this info is ready...
    });
    return _currentShow;
}

现在,您可以利用Apple提供的正确单身UIApplicationDelegate,并最终获得一个Show的不变的实例,可以通过调用(YourApplicationClass*)[[UIApplication sharedApplication] currentShow]

在您应用的任何位置访问该实例

请记住,dispatch_once与App Lifecycle相关联。当且仅当应用程序终止时,它才会被清除,这可能是在您的应用程序处于后台时。

单身人士很难正确实施,甚至更难以确定他们的使用何时得到保证,因此您可能需要查看NSUserDefaults,看看它是否有可以弯曲到您的目的而不是。

答案 1 :(得分:1)

考虑使用this单例实现:

// ShowSingleton.h

#import <Foundation/Foundation.h>
#import "Show.h"

@interface ShowSingleton : NSObject

+ (instancetype)singleton;

@end

// ShowSingleton.m

#import "ShowSingleton.h"

@implementation ShowSingleton

+ (instancetype)singleton {
   static id sharedInstance = nil;

   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^{
      sharedInstance = [[self alloc] init];
   });

   return sharedInstance;
}

@end