Как использовать arrayWithContentsOfFile для загрузки файла, успешно записанного с помощью writeToFile в ObjectiveC/XCode


Я сохраняю массив пользовательских объектов в файл списка plist следующим образом:

+(void) arrayToPlist: (NSArray*) plant_types{
    NSMutableArray* dictionary_array = [NSMutableArray arrayWithCapacity: plant_types.count];

    for(int i = 0; i<plant_types.count; i++){
        PlantType* pt = [plant_types objectAtIndex: i];
        [dictionary_array addObject: [pt toDict]];
    }

    NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString* filePath    = [rootPath stringByAppendingPathComponent:@"PlantTypes.plist"];
    NSLog(@"Writing plist to: %@", filePath);

    [dictionary_array writeToFile: filePath atomically: YES];  
}

Который создает файл, который выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <dict>
        <key>name</key>
        <string>Autumn Olive</string>
        <key>radius</key>
        <real>10</real>
    </dict>
    <dict>
        <key>name</key>
        <string>Dwarf Cherry</string>
        <key>radius</key>
        <real>5</real>
    </dict>
    <dict>
        <key>name</key>
        <string>Bamboo</string>
        <key>radius</key>
        <real>2</real>
    </dict>
    <dict>
        <key>name</key>
        <string>Pomegranate</string>
        <key>radius</key>
        <real>6</real>
    </dict>
    <dict>
        <key>name</key>
        <string>Lupin</string>
        <key>radius</key>
        <real>0.60000002384185791</real>
    </dict>
</array>
</plist>

И загружаем их следующим образом:

+(NSMutableArray*) arrayFromPlist{
    NSLog(@"Loading array of plant types from plist.");

    NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString* filePath    = [rootPath stringByAppendingPathComponent:@"PlantTypes.plist"];
    NSFileManager*  fileManager = [NSFileManager defaultManager];

    if([fileManager fileExistsAtPath:filePath]){ 
        NSLog(@"Plist file exists at expected location.");
        NSMutableArray* plant_dicts = [NSMutableArray arrayWithContentsOfFile:filePath];
        NSLog(@"Loaded array with contents of file, got %d plant types.", plant_dicts.count);
        NSMutableArray* plant_types = [NSMutableArray arrayWithCapacity: plant_dicts.count];
        for(int i = 0; i< plant_dicts.count; i++){
            NSMutableDictionary* dict = [plant_dicts objectAtIndex: i];
            [plant_types addObject: [PlantType fromDict: dict]];
        }
        return plant_types;
    }
    NSLog(@"Plant Type plist file not found.");
    return NULL;
}

Ничего не рушится, но каждый раз я возвращаю NSMutableArray нулевого размера (и этот оператор регистрации подтверждает, что plant_dicts имеет нулевой размер).

Что я делаю не так? Все подобные проблемы, которые я вижу с arrayWithContentsOfFile:, - это люди, создающие plist вручную или с помощью редактора...Я бы подумал, что делаю это из кода. у него самого не было бы таких проблем...

Edit: я подтвердил, что больше не получаю результат нулевого размера (что странно, в этом разделе не было никаких изменений кода с момента первоначального сообщения). Однако я все еще не загружаю вещи правильно. Вот мои методы фромдикта и тодикта.

Проблема в том, что строка "shape", похоже, не загружается правильно. По крайней мере, когда я спрашиваю, есть ли shape == @"Circle", я получаю, что это не так, даже если это явно происходит в операторе NSLog. Я делаю идентичное сравнение в другом месте кода (при проверке того, как визуализировать объект), и там оно работает нормально (поэтому я предполагаю, что нет никаких странных == vs .равно как и в Java).

Двойное редактирование: подождите, нет [shape isEqualToString: @"Circle"]....почему мне не нужно было использовать его раньше, смущает меня, но добавление его здесь помогает.

2 6

2 ответа:

С помощью plist этот код возвращает правильный результат

+(NSMutableArray*) arrayFromPlist{
    NSLog(@"Loading array of plant types from plist.");

    NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString* filePath    = [rootPath stringByAppendingPathComponent:@"PlantTypes.plist"];
    NSFileManager*  fileManager = [NSFileManager defaultManager];

    if([fileManager fileExistsAtPath:filePath]){ 
        NSLog(@"Plist file exists at expected location.");
        NSMutableArray* plant_dicts = [NSMutableArray arrayWithContentsOfFile:filePath];
        NSLog(@"Loaded array with contents of file, got %d plant types.", plant_dicts.count);
        NSMutableArray* plant_types = [NSMutableArray arrayWithCapacity: plant_dicts.count];
        for(int i = 0; i< plant_dicts.count; i++){
            NSMutableDictionary* dict = [plant_dicts objectAtIndex: i];
            [plant_types addObject: dict];
        }
        return plant_types;
    }
    NSLog(@"Plant Type plist file not found.");
    return NULL;
}

Результат

2012-02-22 16:24:43.697 Test[5574:10103] Loading array of plant types from plist.
2012-02-22 16:24:43.698 Test[5574:10103] Plist file exists at expected location.
2012-02-22 16:24:43.699 Test[5574:10103] Loaded array with contents of file, got 5 plant types.
2012-02-22 16:24:43.700 Test[5574:10103](
        {
        name = "Autumn Olive";
        radius = 10;
    },
        {
        name = "Dwarf Cherry";
        radius = 5;
    },
        {
        name = Bamboo;
        radius = 2;
    },
        {
        name = Pomegranate;
        radius = 6;
    },
        {
        name = Lupin;
        radius = "0.6000000238418579";
    }
)

Я думаю, что проблема исходит из вашей реализации PlantType. Можете ли вы опубликовать свой код (методы toDict и fromDict)

Эта строка:

NSMutableDictionary* dict = [plant_dicts objectAtIndex: i];

Возвращает не изменяемый словарь, а неизменяемый.

Если вы хотите, чтобы он был изменяемым, вы должны сделать что-то в этом роде:

MutableDictionary* dict = [NSMutableDictionary dictionaryWithDictionary: [plant_dicts objectAtIndex: i]];