实现NSOutlineView以编辑plist文件的内容

时间:2010-10-21 21:27:19

标签: objective-c cocoa plist nsoutlineview

我正在使用cocos2d-iphone编写游戏,我们的阶段在.plist文件中定义。但是,文件越来越大 - 所以我开发了一个编辑器,它为进程添加了一些结构,并将大部分plist分解为固定的字段。但是,某些元素仍需要plist编辑器类型功能,所以我在面板上实现了一个NSOutlineView,显示“其他参数”。我试图从XCode的“属性列表编辑器”中复制功能。

我已经实施了以下系统; http://www.stupendous.net/archives/2009/01/11/nsoutlineview-example/

这与我的需求非常接近,但是我今天大部分时间都在试图解决这个问题。通过查找父词典并使用;

,从所选项目“向后”计算键列的值
return [[parentObject allKeysForObject:item] objectAtIndex:0];

但是,当树中给定字典中有多个具有相同值的项时,此语句始终返回具有该值的第一个项(它似乎使用isEqualToString:或哈希值来比较字符串)。这导致键列显示'item1,item1,item1'而不是item1,item2,item3(其中1-3项都具有值'')。我接下来试过了;

-(NSString*)keyFromDictionary:(NSDictionary*)dict forItem:(id)item
{
for( uint i = 0; i < [[dict allKeys] count]; i++ ) {
    id object = [dict objectForKey:[[dict allKeys] objectAtIndex:i]];

    if ( &object == &item ) {
        return [[dict allKeys] objectAtIndex:i];
    }
}   

return nil;
}

但这总是会返回 nil 。我希望那些对NSOutlineView有更多经验的人可能能够提供更好的解决方案。虽然此问题仅在链接示例中出现一次,但是在从字典中删除项目时我不得不多次使用此问题。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

return [[parentObject allKeysForObject:item] objectAtIndex:0];
     

但是,当树中给定字典中有多个具有相同值的项时,此语句始终返回具有该值的第一个项...

嗯,是的。这就是你告诉它要做的事情:“给我这个价值的所有钥匙;给我数组中的第一项;返回“。

  

...此语句始终返回具有该值的第一个项(它似乎使用isEqualToString:或哈希值来比较字符串)。

这不是那种做法的说法;它是字典的工作原理:每个键只能在字典中一次,并且只能有一个对象作为其值,这是使用键的哈希和发送键isEqual:消息(而不是NSString)强制执行的。 - 特定isEqualToString: - 键不需要是字符串*)。

另一方面,这些价值并不是一成不变的。任意数量的键都可以具有相同的值。这就是为什么从值到密钥 - 特别是一个密钥 - 是如此有问题。

*无论如何都不在NSDictionary中。当您尝试生成plist输出时,如果字典包含任何非字符串键,它将进行barf。

  

我接下来试过了;

-(NSString*)keyFromDictionary:(NSDictionary*)dict forItem:(id)item
{
    for( uint i = 0; i < [[dict allKeys] count]; i++ ) {
        id object = [dict objectForKey:[[dict allKeys] objectAtIndex:i]];

        if ( &object == &item ) {
            return [[dict allKeys] objectAtIndex:i];
        }
    }   

    return nil;
}
     

但这总是会返回nil。

这是代码中最少的问题。

首先,在对NSArray进行迭代时,除非绝对需要,否则通常不应使用索引。使用fast enumeration会更清晰。

其次,当你需要索引到NSArray时,正确的类型是NSUInteger。如果你能提供帮助,请不要混用和匹配类型。

第三,我不知道你对那里的地址运算符有什么意义,但你实际做的是取这两个变量的地址。因此,您比较了局部变量object是否与参数变量item是同一个变量。由于它们不是同一个变量,因此该测试总是返回false,这就是为什么你永远不会返回一个对象 - 唯一的另一个退出点返回nil,这就是经常发生的事情。

此代码和早期版本的问题在于您尝试从一个值转到单个键,这与字典的工作方式相反:只有键是唯一的;任意数量的键都可以具有相同的值。

您需要使用其他内容作为项目。使用键作为项目将是一种方式;使model object表示每一行将是另一行。

如果你去模型 - 对象路线,不要忘记防止同一个虚拟字典中的多个行具有相同的键。 NSMutableSet加上实现hashisEqual:会有所帮助。

您可能也应该对数组的处理进行相同的更改。

答案 1 :(得分:0)

为了澄清,我最终通过为plist文件中的每个集合创建代理对象来解决这个问题(因此,对于每个NSMutableArray或NSMutableDictionary)。这意味着我基本上镜像了Plist结构,并将引用包含在每个级别的原始对象中。这允许我存储每个对象或字典键的数组索引,因此在将项目从大纲视图保存回Plist结构时,我在代理对象上使用了“key”或“index”属性。