initWithCoder工作,但init似乎覆盖了我的对象属性?

时间:2010-06-05 17:10:52

标签: objective-c

我一直在努力教自己如何使用NSCoder的存档/取消归档方法,但我很难过。

我有一个我用8个NSInteger属性定义的Singleton类。我试图将此对象保存到磁盘,然后根据需要从磁盘加载。

我已经将保存部分关闭了,我也将负载部分关闭(根据NSLogs),但在我的“initWithCoder:”方法适当地加载对象的属性后,“init”方法运行并重置我的对象的属性回归零。

我可能在这里遗漏了一些基本的东西,但感谢任何帮助!

我对Singleton类的类方法:

+ (Actor *)shareActorState
{
    static Actor *actorState;

    @synchronized(self) {
        if (!actorState) {
            actorState = [[Actor alloc] init];
        }
    }

    return actorState;  
}


-(id)init
{
    if (self = [super init]) {

        NSLog(@"New Init for Actor started...\nStrength: %d", self.strength);
    }

    return self;
}

-(id)initWithCoder:(NSCoder *)coder
{

    if (self = [super init]) {

        strength = [coder decodeIntegerForKey:@"strength"];
        dexterity = [coder decodeIntegerForKey:@"dexterity"];
        stamina = [coder decodeIntegerForKey:@"stamina"];
        will = [coder decodeIntegerForKey:@"will"];
        intelligence = [coder decodeIntegerForKey:@"intelligence"];
        agility = [coder decodeIntegerForKey:@"agility"];
        aura = [coder decodeIntegerForKey:@"aura"];
        eyesight = [coder decodeIntegerForKey:@"eyesight"];
        NSLog(@"InitWithCoder executed....\nStrength: %d\nDexterity: %d", self.strength, self.dexterity);
        [self retain];

    }

    return self;                 
}

-(void) encodeWithCoder:(NSCoder *)encoder
{
    [encoder encodeInteger:strength forKey:@"strength"];
    [encoder encodeInteger:dexterity forKey:@"dexterity"];
    [encoder encodeInteger:stamina forKey:@"stamina"];
    [encoder encodeInteger:will forKey:@"will"];
    [encoder encodeInteger:intelligence forKey:@"intelligence"];
    [encoder encodeInteger:agility forKey:@"agility"];
    [encoder encodeInteger:aura forKey:@"aura"];
    [encoder encodeInteger:eyesight forKey:@"eyesight"];
    NSLog(@"encodeWithCoder executed....");
}


-(void)dealloc
{
    //My dealloc stuff goes here
    [super dealloc];
}

当谈到这些东西并且上个月一直在努力教我自己时,我是一个菜鸟,所以原谅任何明显的事情。

感谢您的帮助!

3 个答案:

答案 0 :(得分:2)

我一直使用以下模板,并发现它非常有用。单例状态的加载和保存是封装的,您所要做的就是要求共享实例。您可能希望公开persistToStorage并从应用委托的applicationWillTerminate:方法中调用它。

(您可能希望使此线程更安全。)

static Actor*       SharedActor;

+(Actor*)sharedActor
{
    if (SharedActor)
        return SharedActor;

    SharedActor = [[NSKeyedUnarchiver unarchiveObjectWithFile:[self actorDataFileName]]retain];
    if (!SharedActor)
        SharedActor = [[Actor alloc]init];

    return SharedActor;
}

+(NSString*)actorDataFileName
{
    NSString* path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    return [path stringByAppendingPathComponent:@"actor.dat"];
}

-(BOOL)persistToStorage
{
    return [NSKeyedArchiver archiveRootObject:self toFile:[Actor userDataFileName]];
}

-(void) encodeWithCoder:(NSCoder *)encoder
{
    [encoder encodeInteger:strength forKey:@"strength"];
    . . .
}

-(id)initWithCoder:(NSCoder *)decoder 
{
    if (self = [super init])
    {
        strength = [decoder decodeIntegerForKey:@"strength"];
        . . .
    }
}

有几件事:

  • 不要执行此操作:[self retain];
  • 归档单身人士并不奇怪......

答案 1 :(得分:1)

我不确定有一个归档/取消归档的单例类是否合理。执行Actor *actor = [Actor shareActorState];时,您正在访问共享实例。如果您然后归档NSData *data = [NSKeyedArchiver archivedDataWithRootObject:actor],那么您将保存正确的内容。

但是,当您取消归档时,您打算做什么? Actor *newactor = [NSKeyedUnarchiver unarchiveObjectWithData:data];创建了一个新角色。它位于共享演员的新内存区域。此newactor与单身[Actor shareActorState]不同,并且违反了设计模式,因为您现在拥有多个对象。

更有可能的是,您希望在Actor类上实现两个实例方法。他们将是:

- (NSData *)archiveStateToData;
- (void)unarchiveStateFromData:(NSData *)data;

实际上会更新实例中的值(使用归档)。如果您正在尝试学习NSCoding协议以及如何归档/取消归档数据,我建议不要使用单例进行。

答案 2 :(得分:0)

虽然我同意@wbyoung你可能不应该归档/取消归档一个单身人士(除非你要经历NSUserDefaults),如果你这样做我相信它会起作用只是改变

-(id)initWithCoder:(NSCoder *)coder
{

    if (self = [super init]) {

-(id)initWithCoder:(NSCoder *)coder
{

    if (self = [self shareActorState]) {

(哦,我会将shareActorState重命名为sharedActorState,或者更好的是sharedActor)