Я храню набор данных в .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
когда все это изменяемо.
Существует ли более легкий/лучше способ сделать это? Если это имеет значение, мои данные являются просто целыми числами и булевскими переменными.
Вместо того, чтобы писать все таможенные классы, вы должны использовать NSPROPERTILISERIZATION
. В частности, см. В PropertyListwithData: Опции: Формат: Ошибка:
Метод. Пример использования:
NSMutableDictionary *d = [NSPropertyListSerialization propertyListWithData:[NSData dataWithContentsOfFile:@"path/to/file"]
options:NSPropertyListMutableContainers
format:NULL
error:NULL];
Это сделает все контейнеры MiCable, но сохраняют узелки листьев (например, NSStrings). Существует также возможность сделать листья смешанными тоже.
Я обычно упрощает создание одного или нескольких пользовательских классов для обработки загрузки и сохранения. Это позволяет конвертировать массивы в 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];
То, что вы хотите, это глубокая смежная копия. Какао не включает способ сделать это. Несколько человек написали такие реализации в глубокой копии до ( пример ).
Тем не менее, основной фонд включает в себя CFPROPERTYLIST API , который имеет поддержку как для создания глубоких смежных копий объектов объектов свойств, а также считывания в списках свойств от диска в качестве изменяемых данных. (И, конечно же, типы списков недвижимости основных фондов являются бесплатные модифицированные с какао, что означает, что вам не нужно преобразовывать между ними - NSARRAY - это CFARRAY и VICE-VERSA.)