我正在使用 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(其中 item 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 有更多经验的人能够提供更好的解决方案。虽然这个问题只在链接的示例中出现一次,但我在从字典中删除项目时不得不多次使用这个问题。任何帮助将不胜感激。
最佳答案
return [[parentObject allKeysForObject:item] objectAtIndex:0];
However, when there are multiple items with the same value within a given dictionary in the tree, this statement always returns the first item that has that value …
嗯,是的。这就是你告诉它要做的事情:“给我这个值的所有键;获取数组中的第一项;返回”。
… this statement always returns the first item that has that value (it appears to compare the strings using isEqualToString: or hash values).
不是那个语句在做这件事;而是这个语句在做这件事。这就是字典的工作原理:每个键只能在字典中出现一次,并且只能有一个对象作为其值,这是通过使用键的哈希值并通过发送键 isEqual:
消息来强制执行的(不是特定于 NSString 的 isEqualToString:
——键不需要是字符串*)。
另一方面,这些值并不是唯一的。任意数量的键可以具有相同的值。这就是为什么从值到键(尤其是键)是如此有问题的原因。
*无论如何,不在 NSDictionary 中。当您尝试生成 plist 输出时,如果字典包含任何非字符串键,它将失败。
I next tried;
-(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; }
But this always returns nil.
这是代码中最不存在的问题。
首先,当迭代 NSArray 时,除非绝对需要,否则通常不应使用索引。使用起来更干净fast enumeration .
其次,当您确实需要 NSArray 中的索引时,正确的类型是 NSUInteger
。如果可以的话,不要混合搭配类型。
第三,我不知道你对地址运算符的意思是什么,但你实际上所做的是获取这两个变量的地址。因此,您比较了局部变量 object
与参数变量 item
是否是同一变量。由于它们不是同一个变量,因此该测试始终返回 false,这就是为什么您从不返回对象的原因 - 唯一的其他退出点返回 nil
,所以这就是总是发生的情况。
此代码和早期单行代码的问题在于,您试图从一个值转换为单个键,这与字典的工作方式相反:只有键是唯一的;任意数量的键可以具有相同的值。
您需要使用其他东西作为元素。使用 key 作为元素是一种方法;制作model object代表每一行将是另一行。
如果您采用模型-对象路线,请不要忘记防止同一虚拟字典中的多行具有相同的键。 NSMutableSet 加上实现 hash
和 isEqual:
将对此有所帮助。
您可能还应该对数组的处理进行相同的更改。
关于objective-c - 实现 NSOutlineView 来编辑 plist 文件的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3992106/