Singleton被取消分配

时间:2012-10-09 14:47:49

标签: objective-c ios ios5 cocos2d-iphone ios6

我创建了一个简单的单例类来保存项目的静态数据。 我第一次访问这个单例是我的Cocos2d场景中的onEnter方法。但是当我尝试稍后在另一个方法(同一场景)中再次访问它时,这个单例已经被释放了。我很困惑,如何防止我的单身人士被解除分配?

这是我的单身人士的界面部分:

#import <Foundation/Foundation.h>

@interface OrchestraData : NSObject
+(OrchestraData *)sharedOrchestraData;
@property (retain, readonly) NSArray *animalNames;
@end

实现:

#import "OrchestraData.h"

@implementation OrchestraData
@synthesize animalNames = animalNames_;

+(OrchestraData*)sharedOrchestraData
{
    static dispatch_once_t pred;
    static OrchestraData *_sharedOrchestraData = nil;

    dispatch_once(&pred, ^{ _sharedOrchestraData = [[OrchestraData alloc] init]; });
    return _sharedOrchestraData;
}

-(id)init {
    if (self = [super init]) {
        animalNames_ = [NSArray arrayWithObjects:@"giraffe", @"giraffe", @"giraffe", @"giraffe", nil];
    }
    return self;
}
@end

我正在以这种方式使用我的单身人士:

[[OrchestraData sharedOrchestraData] animalNames];

更新: 在NSZombies启用的情况下,我重新审视了它,看起来好像我的NSArrays已经发布了,而不是单例本身。我该怎么办?

4 个答案:

答案 0 :(得分:4)

您必须以这种方式实施单身人士:

1)在您的Singleton类的.h文件中:

+ (SingletonClass *)instance;

2)在.m文件中:

+ (SingletonClass *)instance {

    static SingletonClass* instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
        //your init code here
    });
    return instance;
}

如果您想呼叫您的单身人士,请拨打[SingletonClass instance]

如果你感兴趣的是什么是“dispatch_once_t”,请阅读Grand Central Dispatch: http://developer.apple.com/library/ios/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html

答案 1 :(得分:2)

RE更新:

您的NSArray已取消分配,因为您正在使用autorelease初始化程序arrayWithObjects并将其直接分配给ivar animalNames_。因此不予保留。

要解决此问题,请将数组分配给属性:

self.animalNames = [NSArray arrayWithObjects:@"giraffe", @"giraffe", @"giraffe", @"giraffe", nil];
顺便说一句,在ARC下,这不是一个问题,因为ivar本来是一个强大的(保留)参考。我不会厌倦鼓励任何人切换到ARC。它已经有一年多的时间了,而且使用MRC代码绝对没有意义!看到开发人员仍然没有使用更简单,更快捷,更直接的选项,我真的很痛苦。 (咆哮):)

答案 2 :(得分:-2)

您可以在任何需要的位置设置指针。

-(void)someMethod {

MySingleton *singleton = [MySingleton sharedSingleton];
singleton.data = YES; //dumb example to show you did something...

}

-(void)someOtherMethod {

MySingleton *singleton = [MySingleton sharedSingleton]; //You have to create a new pointer...
singleton.data = NO; //another dumber example to show you did something...

}

注意:这假设你创建了一个单身的方式与我的方式相同......你的代码可能会有所不同,因此导致我的答案不适用......

答案 3 :(得分:-3)

你需要在你的单例类中覆盖下面的方法,因为在你的程序中,如果有人初始化了[[SingletonClass alloc] init],那么单例将有另一个实例并释放它将导致错误。

+ (id)allocWithZone:(NSZone *)zone{
    return [[self SingletonClass] retain];  
}

- (id)copyWithZone:(NSZone *)zone{
    return self;
}

- (id)retain{
    return self;
}