代码之家  ›  专栏  ›  技术社区  ›  kbanman

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

  •  5
  • kbanman  · 技术社区  · 15 年前

    我在.plist文件(在application documents文件夹中)中存储了大量数据,其结构如下:

    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 回复  |  直到 15 年前
        1
  •  9
  •   Colin Barrett    15 年前

    您应该使用 NSPropertyListSerialization . 具体来说,请参见 propertyListWithData:options:format:error: 方法。示例用法:

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

    这将使所有容器都可变,但保持叶节点(例如nsstrings)不变。还有一个选择,使树叶也可变。

        2
  •  8
  •   James Eichele Bernard Igiri    15 年前

    我通常发现创建一个或多个自定义类来处理加载和保存更容易。这允许您显式地将数组转换为mutableArrays:

    我的生活

    @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
    

    我的东西

    @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];
    
        3
  •  1
  •   Chuck    15 年前

    你想要的是一个深度可变的副本。可可不包括这样做的方法。一些人以前写过如此深入的副本实现( example )

    然而,核心基础包括 CFPropertyList API 它既支持创建属性列表对象的深度可变副本,也支持将属性列表作为可变数据类型从磁盘中读取。(当然,核心基金会的属性列表类型与COCOA的免费桥接,意味着您不必在它们之间转换),NSARCURE是CFARAL,反之亦然。