initWithCoder работает, но init, кажется, перезаписывает свойства моих объектов? - PullRequest
1 голос
/ 05 июня 2010

Я пытался научить себя, как использовать методы архивации / разархивирования NSCoder, но я в замешательстве.

У меня есть класс Singleton, который я определил с помощью 8 свойств NSInteger. Я пытаюсь сохранить этот объект на диск, а затем загрузить с диска при необходимости.

У меня есть часть сохранения, и у меня также есть часть загрузки (согласно 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 ]

2 голосов
/ 05 июня 2010

Я все время пользуюсь следующим шаблоном и нахожу его очень полезным. Загрузка и сохранение состояния синглтона инкапсулируется, и все, что вам нужно сделать, - это запросить общий экземпляр. Возможно, вы захотите сделать 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 голос
/ 05 июня 2010

Я не уверен, что имеет смысл иметь одноэлементный класс, который заархивирован / разархивирован. Когда вы делаете 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 и как архивировать / разархивировать данные, я бы порекомендовал не делать это с одиночным.

0 голосов
/ 05 июня 2010

Хотя я согласен с @wbyoung, что вы , вероятно, не должны архивировать / разархивировать синглтон (если вы не проходите через NSUserDefaults), но если вы сделаете это, я думаю, это сработает меняется

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

    if (self = [super init]) {

до

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

    if (self = [self shareActorState]) {

(о, и я бы переименовал shareActorState в sharedActorState или, что еще лучше, sharedActor)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...