1

我正在使用 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 有更多经验的人能够提供更好的解决方案。虽然这个问题在链接的例子中只出现过一次,但在从字典中删除项目时,我不得不多次使用它。任何帮助将不胜感激。

4

2 回答 2

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

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

嗯,是的。这就是你告诉它要做的事情:“给我这个值的所有键;给我数组中的第一项;归还”。

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

不是那个声明在做它;这就是字典的工作原理:每个键只能在字典中出现一次,并且只能有一个对象作为其值,这是通过使用键的哈希和发送键isEqual:消息(不是特定于 NSString 的键isEqualToString:是不需要是字符串*)。

另一方面,这些值并不是唯一的。任意数量的键可以具有相同的值。这就是为什么从值到键——尤其键——如此成问题的原因。

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

我接下来尝试了;

-(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 时,通常不应该使用索引,除非绝对需要。使用快速枚举要干净得多。

其次,当您确实需要 NSArray 的索引时,正确的类型是NSUInteger. 当你可以帮助它时,不要混合和匹配类型。

第三,我不知道您对那里的 address-of 运算符的意思是什么,但您实际上所做的是获取这两个变量的地址。因此,您比较了局部变量object是否与参数变量相同item。由于它们不是同一个变量,因此该测试始终返回 false,这就是为什么您永远不会返回对象的原因——唯一的另一个出口点返回nil,所以总是会发生这种情况。

这段代码和前面的单行代码的问题在于,您试图从一个值转到单个键,这与字典的工作方式相反:只有键是唯一的;任意数量的键可以具有相同的值。

您需要使用其他东西作为项目。使用钥匙作为物品是一种方法;制作一个模型对象来表示每一行将是另一个。

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

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

于 2010-10-22T16:13:03.190 回答
0

To clarify, I eventually resolved this problem by creating proxy objects for each of the collections in the plist file (so, for every NSMutableArray or NSMutableDictionary). This meant that I essentially mirrored the Plist structure and included references back to the original objects at each level. This allowed me to store the array index for each object or the dictionary key, so when saving items back from the outline view to the Plist structures, I used the 'key' or 'index' properties on the proxy object.

于 2010-11-02T11:44:42.367 回答