存储和检索多维NSMutableArrays的最佳方法是什么?

kba*_*man 5 iphone objective-c plist nsmutablearray nsmutabledictionary

我将一堆数据存储在.plist文件中(在应用程序文档文件夹中),它的结构如下:

Dictionary {
    "description" = "String Value",
    "sections" = Array (
        Array (
            Number,
            ...
            Number
        ),
        Array (
            Number,
            ...
            Number
        )
    ),
    "items" = Array (
        Array (
            Number,
            ...
            Number
        ),
        Array (
            Number,
            ...
            Number
        )
    )
}
Run Code Online (Sandbox Code Playgroud)

如果我只是检索它
NSMutableDictionary *d = [[NSMutableDictionary alloc] initWithContentsOfFile:plistFile] 我将无法替换数字对象,对吗?所以我现在正在通过数据递归并形成整个事物的可变版本,并且它在一个实例中工作,但现在它告诉我mutating method sent to immutable object什么时候整个事情是可变的.

有没有更容易/更好的方法来做到这一点?如果它有所作为,我的数据只是整数和布尔值.

Col*_*ett 9

您应该使用而不是编写所有自定义类垃圾NSPropertyListSerialization.具体来说,请参阅propertyListWithData:options:format:error:方法.用法示例:

NSMutableDictionary *d = [NSPropertyListSerialization propertyListWithData:[NSData dataWithContentsOfFile:@"path/to/file"] 
                                                                   options:NSPropertyListMutableContainers
                                                                    format:NULL
                                                                     error:NULL];
Run Code Online (Sandbox Code Playgroud)

这将使所有容器都可变,但保持叶节点(例如NSStrings)不可变.还有一个选项可以使叶子变得可变.


e.J*_*mes 8

我通常发现创建一个或多个自定义类来处理加载和保存更容易.这允许您显式地将数组转换为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
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)

做完这些后,你可以封装都在你的包装和拆开的代码loadFromFilesaveToFile方法.这种方法的主要好处是您的主程序变得更加简单,并且它允许您作为属性访问数据结构的元素:

MyThing * thing = [[MyThing alloc] init];
[thing loadFromFile:@"..."];
...
thing.description = @"new description";
[thing.sections addObject:someObject];
[thing.items removeObjectAtIndex:4];
...
[thing saveToFile:@"..."];
[thing release];
Run Code Online (Sandbox Code Playgroud)