我创建了一个简单的单例类来保存项目的静态数据。 我第一次访问这个单例是我的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已经发布了,而不是单例本身。我该怎么办?
答案 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;
}