我正在使用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有更多经验的人可能能够提供更好的解决方案。虽然此问题仅在链接示例中出现一次,但是在从字典中删除项目时我不得不多次使用此问题。任何帮助将不胜感激。
答案 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加上实现hash
和isEqual:
会有所帮助。
您可能也应该对数组的处理进行相同的更改。
答案 1 :(得分:0)
为了澄清,我最终通过为plist文件中的每个集合创建代理对象来解决这个问题(因此,对于每个NSMutableArray或NSMutableDictionary)。这意味着我基本上镜像了Plist结构,并将引用包含在每个级别的原始对象中。这允许我存储每个对象或字典键的数组索引,因此在将项目从大纲视图保存回Plist结构时,我在代理对象上使用了“key”或“index”属性。