使用 NSCoder 初始化静态单例对象
我正在开发一个 iPhone 应用程序,并且在共享单例类方面遇到了一些麻烦。 我使用共享单例来存储两个变量 int gameRuns
和 int totalScore
每次用户加载应用程序时,“gamRuns”都会递增,并且“totalScore”很明显:D
问题如下,当使用此代码加载应用程序时,我使用自己的方法加载单例和初始化:
+ (SingletonLevelState*)sharedLevelStateInstance {
static SingletonLevelState *sharedLevelStateInstance;
@synchronized(self) {
if(!sharedLevelStateInstance) {
//Init a singleton
sharedLevelStateInstance = [[SingletonLevelState alloc] init];
sharedLevelStateInstance->gameRuns = 1;
sharedLevelStateInstance->totalScore = 0;
}
}
return sharedLevelStateInstance;
}
这工作得很好,因为我可以从任何其他类引用此类,并且始终获取指向同一对象的指针,因此这对于其他对象来说效果很好:
sharedLevelState = [SingletonLevelState sharedLevelStateInstance];
sharedLevelStateInstance.gameRuns++;
现在我添加了 NSCoder 协议,并添加了两个方法 initWithCoder
和encodeWithCoder
如下:
- (void) encodeWithCoder: (NSCoder *)coder
{
//encode level data
[coder encodeInt:self->gameRuns forKey:@"gameRuns"];
[coder encodeInt:self->totalScore forKey:@"totalScore"];
}
- (id) initWithCoder: (NSCoder *) coder
{
if(self = [super init]){
self->gameRuns = [coder decodeIntForKey:@"gameRuns"];
self->totalScore = [coder decodeIntForKey:@"totalScore"];
}
return self;
}
现在,当应用程序加载时,我检查是否已经保存了状态,如果存在,我只需使用该文件取消归档该类,如果没有,我使用以下命令初始化该类我上面的自定义方法,然后设置其默认值,将其编码到文件中,以便我们有一个保存的状态,代码如下:
//Load Level state
sharedLevelStateInstance = [SingletonLevelState sharedLevelStateInstance];
//Check if file is saved
NSFileManager *fm = [[NSFileManager alloc] init];
NSString *gameStatePath = [NSString stringWithString:[self getSavePath]];
if([fm fileExistsAtPath:gameStatePath]){
[self loadState];
sharedLevelStateInstance.gameRuns = sharedLevelStateInstance.gameRuns+1;
NSLog(@"Loaded %d times", [sharedLevelStateInstance gameRuns]);
}
[fm release];
现在 if 语句中的最后一行完美运行,每次我按预期加载应用程序时它都会递增 我真的感觉快乐哈哈。
但是,当我尝试通过执行以下操作来获取另一个类中单例的引用时,问题就出现了:
sharedLevelStateInstance = [SingletonLevelState sharedLevelStateInstance];
NSLog(@"Played: %d times", sharedLevelStateInstance.gameRuns);
它总是倒数到 1,我知道会发生什么,但我不起诉什么是最好的解决这个问题的方法是,当我 initWithCoder
单例时,它不会返回静态对象,而是创建一个新对象,当我初始化我的 sharedLevelStateInstance
时,它会调用我的第一个自定义对象方法,将其初始化为硬编码的默认值。
StackOverflow,你能帮帮我吗?!
我只需要知道获取对同一对象的引用的最佳方法是什么,而无需每次 initWithCoder
都分配一个新对象!
谢谢 :)
I'm working on an iPhone app and facing some troubles with my shared singleton class.
I'm using a shared singleton to store two variablesint gameRuns
and int totalScore
'gamRuns' just increments every time the user loads the app, and 'totalScore' is obvious :D
the issue is as follows, I load the singleton and init using my own method when the app loads using this code:
+ (SingletonLevelState*)sharedLevelStateInstance {
static SingletonLevelState *sharedLevelStateInstance;
@synchronized(self) {
if(!sharedLevelStateInstance) {
//Init a singleton
sharedLevelStateInstance = [[SingletonLevelState alloc] init];
sharedLevelStateInstance->gameRuns = 1;
sharedLevelStateInstance->totalScore = 0;
}
}
return sharedLevelStateInstance;
}
This is working great as I can reference this class from any other class and always get a pointer to the same object, so this works fine from other objects:
sharedLevelState = [SingletonLevelState sharedLevelStateInstance];
sharedLevelStateInstance.gameRuns++;
Now I added the NSCoder protocol, and added the two methods initWithCoder
and encodeWithCoder
as follows :
- (void) encodeWithCoder: (NSCoder *)coder
{
//encode level data
[coder encodeInt:self->gameRuns forKey:@"gameRuns"];
[coder encodeInt:self->totalScore forKey:@"totalScore"];
}
- (id) initWithCoder: (NSCoder *) coder
{
if(self = [super init]){
self->gameRuns = [coder decodeIntForKey:@"gameRuns"];
self->totalScore = [coder decodeIntForKey:@"totalScore"];
}
return self;
}
Now when the app loads, I check to see if we already have a saved sate, if it exists, I just unarchive the class with that file, if not, I init that class using my custom method above, then set its defaults, encode it to file so we have a saved state, here's the code:
//Load Level state
sharedLevelStateInstance = [SingletonLevelState sharedLevelStateInstance];
//Check if file is saved
NSFileManager *fm = [[NSFileManager alloc] init];
NSString *gameStatePath = [NSString stringWithString:[self getSavePath]];
if([fm fileExistsAtPath:gameStatePath]){
[self loadState];
sharedLevelStateInstance.gameRuns = sharedLevelStateInstance.gameRuns+1;
NSLog(@"Loaded %d times", [sharedLevelStateInstance gameRuns]);
}
[fm release];
Now the last line in the if statement works perfectly, it increments every time I load the app as expected and I feel really happy lol.
However, the problem arises when I try to get a reference of the singleton in another class by doing the following:
sharedLevelStateInstance = [SingletonLevelState sharedLevelStateInstance];
NSLog(@"Played: %d times", sharedLevelStateInstance.gameRuns);
It always counts back to 1, I know what happens but I'm not sue what's the best way to solve it, when I initWithCoder
the singleton, It's not returning a static object, it creates a new one, when I init my sharedLevelStateInstance
, it calls my first custom method, initializing it to the defaults hardcoded.
So StackOverflow, can you please help me ?!
I just need to know what's the best way to get a reference to the same object without allocating a new one every time I initWithCoder
!
Thanks :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
因此,您的代码可能应该如下所示:
设置单例的变量,并返回单例。请务必保留单例,以便当 NSCoder 释放此实例时,它不会完全释放您的单例。
So, you code should probably look like this:
Which sets the variables of the singleton, and returns the singleton. Be sure to retain the singleton, so that when the
NSCoder
releases this instance, it doesn't fully deallocate your singleton.