objective-c - 实现 NSOutlineView 来编辑 plist 文件的内容

标签 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(其中 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 加上实现 hashisEqual: 将对此有所帮助。

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

关于objective-c - 实现 NSOutlineView 来编辑 plist 文件的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3992106/

相关文章:

ios - 从自制模型迁移到核心数据模型 : setter/getter issue

iphone - 检测应用程序的首次运行

iphone - 如何将 AQGridView 合并到一个项目中?

objective-c - object_setClass 到更大的类

objective-c - 使用 xcode 将 Flash 文件作为 OSX 屏幕保护程序

objective-c - 如何在 NSOutlineView 中设置本地化的显示/隐藏按钮

macos - 如何在 NSTextField 中添加 Cocoa 控件?

ios - Plist 到 SQLITE

ios - 来自 ios 中 Plist 的嵌套可扩展 UITableView

iOS autoLayout View 未显示在屏幕上?