NSUserDefaults, NSCoder, Custom Class - вопрос о приложении для iPhone - PullRequest
0 голосов
/ 14 июля 2011

У меня ошибка, и я думаю, что я делаю что-то не так в следующем процессе. Во-первых, у меня есть класс Контакты:

@interface Contact : NSObject<NSCoding> {
    @private
    ABRecordRef ref;
    NSString *first;
    NSString *last;
    bool selected;
    NSString *phoneNumber;
}

А в реализации Contact у меня есть:

- (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:first forKey:@"First"];
    [encoder encodeObject:last forKey:@"Last"];
    [encoder encodeObject:[NSNumber numberWithInteger: ABRecordGetRecordID(ref)] forKey:@"Ref"  ];
    [encoder encodeObject:first forKey:@"PhoneNumber"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    self = [[Contact alloc] init];
    first = [decoder decodeObjectForKey:@"First"];
    last = [decoder decodeObjectForKey:@"Last"];
    ABAddressBookRef addressBook = ABAddressBookCreate();
    NSNumber *num = [decoder decodeObjectForKey:@"Ref"];
    ref = ABAddressBookGetPersonWithRecordID(addressBook,(ABRecordID)num);
    phoneNumber = [decoder decodeObjectForKey:@"PhoneNumber"];

    return self;
}

И когда я создаю в своем приложении то, что я называю «группой», я делаю следующее:

+ (void)addGroupWithName:(NSString *)s contacts:(NSMutableArray *)arr {
    NSLog(@"added group name with name %@",s);
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arr];
    [defaults setObject:data forKey:s];
    [defaults synchronize];
    //[UserData setDefaultWithName:s object:arr];
}

, который, согласно некоторым печатным заявлениям, которые я делаю, кажется, работает нормально.

Затем, когда приложение запускается, я пытаюсь распечатать сохраненные объекты:

+ (void)printGroups {
    NSMutableArray *arr = [UserData getGroupNames];
    NSLog(@"group names are %@",arr);
    for(int i = 0; i < [arr count]; i++) {
        NSString *name = [arr objectAtIndex:i];
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        NSData *data = [defaults objectForKey:name];
        NSArray *a = [NSKeyedUnarchiver unarchiveObjectWithData:data];
        NSLog(@"name = %@",name);
        NSLog(@"array count is %i",[a count]);
        for(int i = 0; i < [a count]; i++) {
            NSLog(@"on index %i",i);
            Contact *c = [a objectAtIndex:i];
            NSLog(@"got contact");
            if(c == nil)
                NSLog(@"it's nil!");    

            NSLog(@"class is %@", NSStringFromClass([c class]));
            NSLog(@"got contact %@",c);
        }
        NSLog(@"array = %@",a);
    }
}

Однако в строке NSLog (@ "got contact% @", c); моя программа перестает работать. Он печатает все отлично, и даже печатает, что класс объекта «Контакт». Но тогда это останавливается. Похоже, что возможно, есть ошибка, но в левой части я просто вижу вопросительные знаки под опцией «По потоку» в XCode 4 в области ошибок слева.

Так что я делаю не так?

enter image description here

Ответы [ 2 ]

0 голосов
/ 14 июля 2011

Hm.Оказалось, если я добавил retain на метод декодирования, все работало.Я имею в виду, сохранить все объекты.

0 голосов
/ 14 июля 2011

Во-первых, ваш init должен выглядеть следующим образом:

- (id)initWithCoder:(NSCoder *)decoder 
{
    if(self = [super init])
    {
        first = [[decoder decodeObjectForKey:@"First"] retain];
        last = [[decoder decodeObjectForKey:@"Last"] retain];
        ABAddressBookRef addressBook = ABAddressBookCreate();
        NSNumber *num = [decoder decodeObjectForKey:@"Ref"];
        ref = ABAddressBookGetPersonWithRecordID(addressBook,(ABRecordID)num);
        phoneNumber = [[decoder decodeObjectForKey:@"PhoneNumber"] retain];
    }

    return self;
}

В encodeWithCoder вы кодируете first дважды, вы, вероятно, хотели phoneNumber во втором.

ВозможноМне не хватает того, где вы создаете новые Contact объекты, но вам, вероятно, понадобится стандартный метод init для первоначального создания контакта (initWithCoder инициализируется только при декодировании из данных или файла, я полагаю).Вероятно, это будет выглядеть примерно так:

- (id)initWithFirst:(NSString *)firstIn last:(NSString *)lastIn phone:(NSString *)phoneIn 
{
    if(self = [super init])
    {
        first = [firstIn retain];
        last = [lastIn retain]; 
        phoneNumber = [phoneIn retain];
        selected = NO;
        ref = //however you generate a record reference
    }

    return self;
}

Я не уверен, если что-то не так, но попробуйте изменить эти две вещи и посмотреть, если это что-то меняет.Убедитесь, что у вас есть dealloc, где вы освобождаете всех своих учеников.

...