Каков наилучший способ хранения и извлечения многомерных NSMutableArrays? - PullRequest
5 голосов
/ 26 января 2010

Я храню кучу данных в файле .plist (в папке документов приложения), и он структурирован так:

Dictionary {
    "description" = "String Value",
    "sections" = Array (
        Array (
            Number,
            ...
            Number
        ),
        Array (
            Number,
            ...
            Number
        )
    ),
    "items" = Array (
        Array (
            Number,
            ...
            Number
        ),
        Array (
            Number,
            ...
            Number
        )
    )
}

Если я просто получу его с помощью
NSMutableDictionary *d = [[NSMutableDictionary alloc] initWithContentsOfFile:plistFile] Я не смогу заменить числовые объекты, правильно? Итак, я рекурсивно проверяю данные прямо сейчас и формирую изменчивую версию всего этого, и это работало в одном случае, но теперь оно говорит мне mutating method sent to immutable object, когда все это изменчиво.

Есть ли более простой / лучший способ сделать это? Если это имеет значение, мои данные просто целые и логические значения.

Ответы [ 3 ]

9 голосов
/ 26 января 2010

Вместо того, чтобы писать все эти ненужные классы, вы должны использовать NSPropertyListSerialization. В частности, см. Метод propertyListWithData:options:format:error:. Пример использования:

NSMutableDictionary *d = [NSPropertyListSerialization propertyListWithData:[NSData dataWithContentsOfFile:@"path/to/file"] 
                                                                   options:NSPropertyListMutableContainers
                                                                    format:NULL
                                                                     error:NULL];

Это сделает все контейнеры изменяемыми, но сохранит неизменность конечных узлов (например, строк NSS). Также есть возможность сделать листья изменчивыми.

8 голосов
/ 26 января 2010

Обычно мне проще создать один или несколько пользовательских классов для обработки загрузки и сохранения. Это позволяет явно преобразовывать массивы в mutableArrays:

MyThing.h

@interface MyThing : NSObject
{
    NSString * description;
    NSMutableArray * sections;
    NSMutableArray * items;
}
@property (copy) NSString * description;
@property (readonly) NSMutableArray * sections;
@property (readonly) NSMutableArray * items;
- (void)loadFromFile:(NSString *)path;
- (void)saveToFile:(NSString *)path;
@end

MyThing.m

@implementation MyThing
@synthesize description;
@synthesize sections
@synthesize items;

- (id)init {
    if ((self = [super init]) == nil) { return nil; }
    sections = [[NSMutableArray alloc] initWithCapacity:0];
    items = [[NSMutableArray alloc] initWithCapacity:0];
    return self;
}

- (void)dealloc {
    [items release];
    [sections release];
}

- (void)loadFromFile:(NSString *)path {
    NSDictionary * dict = [NSDictionary dictionaryWithContentsOfFile:path];
    [self setDescription:[dict objectForKey:@"description"]];
    [sections removeAllObjects];
    [sections addObjectsFromArray:[dict objectForKey:@"sections"]];
    [items removeAllObjects];
    [items addObjectsFromArray:[dict objectForKey:@"items"]]; 
}

- (void)saveToFile:(NSString *)path {
    NSDictionary * dict = [NSDictionary dictionaryWithObjectsAndKeys:
                           description, @"description",
                           sections, @"sections",
                           items, @"items",
                           nil];
    [dict writeToFile:path atomically:YES];
}

@end;

После этого вы можете инкапсулировать весь код упаковки и распаковки в методы loadFromFile и saveToFile. Основным преимуществом этого подхода является то, что ваша основная программа становится намного проще и позволяет вам получить доступ к элементам вашей структуры данных в виде свойств:

MyThing * thing = [[MyThing alloc] init];
[thing loadFromFile:@"..."];
...
thing.description = @"new description";
[thing.sections addObject:someObject];
[thing.items removeObjectAtIndex:4];
...
[thing saveToFile:@"..."];
[thing release];
1 голос
/ 26 января 2010

То, что вы хотите, является глубоко изменяемой копией.Какао не включает в себя способ сделать это.Несколько человек уже писали такие реализации глубокого копирования ( пример ).

Однако Core Foundation включает CFPropertyList API , который поддерживает обе возможности для создания глубоких копий.изменяемые копии объектов списка свойств, а также чтение в списках свойств с диска как изменяемые типы данных.(И, конечно, типы списков свойств Core Foundation бесплатны и связаны с какао, то есть вам не нужно конвертировать между ними - NSArray - это CFArray и наоборот.)

...