Не удается получить NSData в NSMutableArray

У меня есть массив объектов, которые я хочу сохранить в виде файла и перезагрузить обратно в свое приложение. Он сохраняет файл (с некоторыми данными внутри), но я не могу заставить его прочитать обратно в массив NSMutable.

Объекты представляют собой модели, соответствующие протоколу NSCoding:

@implementation myModel

@synthesize name;
@synthesize number;

-(void) encodeWithCoder: (NSCoder *) encoder
{
    [encoder encodeObject:name forKey:@"name"];
    [encoder encodeInteger:number forKey:@"number"];
}

-(id) initWithCoder: (NSCoder *) decoder
{
    name = [decoder decodeObjectForKey:@"name"];
    number = [decoder decodeIntegerForKey:@"number"];
    return self;
}

@end

Итак, я создаю массив этих объектов, затем сохраняю его...

- (void) saveMyOptions {

    // Figure out where we're going to save the app's data files
    NSString *directoryPath = [NSString stringWithFormat:@"%@/Library/Application Support/MyAppDir/", NSHomeDirectory()]; // points to application data folder for user

    // Figure out if that directory exists or not
    BOOL isDir;  

    NSFileManager *fileManager = [[NSFileManager alloc] init];

    [fileManager fileExistsAtPath:directoryPath isDirectory:&isDir];

    // If the directory doesn't exist, create it
    if (!isDir)
    {
        [fileManager createDirectoryAtPath:directoryPath withIntermediateDirectories:YES attributes:nil error:NULL];
    }

    // Assemble everything into an array of objects with options
    NSMutableArray *savedPreferences = [[NSMutableArray alloc] init];

    myModel *saveOptions = nil;

    for (int i; i < [otherArray count]; i++)
    {
        saveOptions = [[myModel alloc] init];

        [saveOptions setName:@"Some String"];
        [saveOptions setNumber:i];        
        [savedPreferences addObject:saveOptions];
        saveOptions = nil;
    }

    // Actually save those options into a file
    NSData* saveData = [NSKeyedArchiver archivedDataWithRootObject:savedPreferences];

    NSString *fileName = [NSString stringWithFormat:@"%@filename.stuff", directoryPath];

    NSError *error = nil;

    BOOL written = [saveData writeToFile:fileName options:0 error:&error];

    if (!written)
    {
        NSLog(@"Error writing file: %@", [error localizedDescription]);
    }

}

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

- (NSMutableArray *) loadOptions {

    // Create file manager object
    NSFileManager *fileManager = [[NSFileManager alloc] init];

    NSData *saveData = nil;

    // Find user directory path
    NSString *directoryPath = [NSString stringWithFormat:@"%@/Library/Application Support/MyAppDir/", NSHomeDirectory()]; // points to application data folder for user

    // Assign file name
    NSString *fileName = [NSString stringWithFormat:@"%@filename.stuff", directoryPath];

    // Create options array
    NSMutableArray *myOptions = nil;

    // If the file exists, fill the array with options
    if ([fileManager fileExistsAtPath:fileName])
    {
        saveData = [NSData dataWithContentsOfFile:fileName];
        myOptions = [NSKeyedUnarchiver unarchiveObjectWithData:saveData];
    } 


    NSLog(@"%lu", [myOptions count]); // This ALWAYS reports 0!
    NSLog(@"%lu", [saveData length]); // This reports a value of 236;

    return myOptions;
}

Может ли кто-нибудь указать мне направление, в котором я ошибаюсь? Я совсем запутался :-(

Заранее спасибо!


person Matthew Jones    schedule 15.03.2012    source источник


Ответы (1)


Вам не хватает вызовов super в ваших методах encodeWithCoder: и initWithCoder:, но это всего лишь предположение. Почему бы не использовать NSUserDefaults для сохранения настроек?

Вы также можете убедиться, что ваши объекты сохраняются с помощью синтезированного установщика.

- (void)encodeWithCoder:(NSCoder *)encoder {
  [super encodeWithCoder:encoder];
  [encoder encodeObject:name forKey:@"name"];
  [encoder encodeInteger:number forKey:@"number"];
}

- (id)initWithCoder:(NSCoder *)decoder {
  self = [super initWithCoder:decoder];
  if (self) {
    self.name = [decoder decodeObjectForKey:@"name"];
    self.number = [decoder decodeIntegerForKey:@"number"];  
  }
  return self;
}

К вашему сведению, NSKeyedArchiver также имеет метод, который вы можете использовать непосредственно для работы с файлами:

+ (BOOL)archiveRootObject:(id)rootObject toFile:(NSString *)path

и NSKeyedUnarchiver:

+ (id)unarchiveObjectWithFile:(NSString *)path
person Erik Aigner    schedule 15.03.2012
comment
супер определенно был частью этого. Спасибо тебе за это! Вторая часть заключалась в том, что я, как идиот, не присвоил i=0, когда зацикливался, чтобы заполнить массив объектами, которые хотел сохранить. Следовательно, цикл никогда не выполнялся, потому что я был нулевым... Хорошо. Большое спасибо за Вашу помощь! - person Matthew Jones; 16.03.2012
comment
Даже не увидел отсутствующий i assign. - person Erik Aigner; 16.03.2012