【问题标题】:Implementing Key Value coding in Objective c在 Objective c 中实现键值编码
【发布时间】:2012-05-23 10:19:11
【问题描述】:

我正在我的程序中实现键值编码,所以我不太适应它。我有控制器类,其中解析方法在开始文档中实现,我已经初始化了对象和键。 Universal 类的所有数据成员都是类型 id。

            univ=[[Universal alloc] init];
            [univ setValue:univ.datamember1 forKey:@"1"];
            [univ setValue:univ.datamember2 forKey:@"2"];
            [univ setValue:univ.datamember3 forKey:@"3"];
            [univ setValue:univ.datamember4 forKey:@"4"];
            [univ setValue:univ.datamember5 forKey:@"5"];

我在结束元素方法中设置数据成员的值:

         id temp1=[univ valueForKey:@"1"];
        temp1=strVal;
        [resultArray addObject:univ];

我收到以下代码异常:

'NSUnknownKeyException', reason: '[<Universal 0x6e994d0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key 1

这是什么原因。是否遗漏了什么或一切都出错了??

【问题讨论】:

    标签: iphone objective-c ipad


    【解决方案1】:

    在大多数情况下,您不必实施键值编码。相反,您可以创建符合各种约定的类,然后 Key-Value Coding 会自动为它工作。

    这些约定是关于如何命名方法以使属性可以通过 KVC 访问。

    您的代码:

            univ=[[Universal alloc] init];
            [univ setValue:univ.datamember1 forKey:@"1"];
            [univ setValue:univ.datamember2 forKey:@"2"];
            [univ setValue:univ.datamember3 forKey:@"3"];
            [univ setValue:univ.datamember4 forKey:@"4"];
            [univ setValue:univ.datamember5 forKey:@"5"];
    

    很奇怪。你想在这里做什么?这段代码看起来就像是在尝试从univ 对象的其他属性中设置univ 对象的属性。那将是多余的。

    我怀疑你认为你在这里建立了同义词或别名——你正在将键“1”映射到属性datamember1。这是不正确的。 -setValue:forKey: 方法用于实际设置属性的值。这很像调用 setter 方法;事实上,它通常会调用一个 setter 方法。

    所以,你写的很像下面这样:

            univ=[[Universal alloc] init];
            [univ set1:univ.datamember1];
            [univ set2:univ.datamember2];
            [univ set3:univ.datamember3];
            [univ set4:univ.datamember4];
            [univ set5:univ.datamember5];
    

    我怀疑这就是你的本意。它可能会帮助您用非 KVC 术语解释您正在尝试做什么。您尝试更改哪些属性(如果是)?你想赋予他们什么价值?仅使用普通的 setter 和 getter 将如何做到这一点?

    后来,你发布了这段代码:

        id temp1=[univ valueForKey:@"1"];
        temp1=strVal;
        [resultArray addObject:univ];
    

    再一次,这很奇怪而且令人困惑。我怀疑您正在尝试更改univ 上的属性值,但这不是该代码完成的任务,即使它可以工作。第一行尝试获取univ 对象的属性值,其中属性的名称为“1”。这不是属性的有效名称。无论如何,它将检索到的值存储到局部变量temp1 中。第二行简单地丢弃第一行的结果并将不同的值存储到本地temp1 变量中。 temp1 变量独立于 univ 对象,尽管刚才它存储了从 univ 对象检索到的结果。更改temp1 不能更改univ(尽管发送temp1 指向的对象可能会更改该对象,并且univ 也可能指向它)。

    在我看来,您还没有准备好使用键值编码。您需要更好地了解基础知识。此外,几乎不需要将键值编码与静态的、编译时已知的键一起使用。键值编码用于在编译时不知道该属性的名称但在运行时将名称 作为数据 时动态访问对象的属性。

    【讨论】:

    • 非常感谢您的精彩解释。其实我也不想使用kvc。但是在我的应用程序中,我必须使用它,尽管我对此并不满意。但我会按照你的建议再过一遍。
    • 不客气。如果您必须使用 KVC,也许您可​​以编辑问题(或询问其他问题)来解释您必须使用的原因。您要满足的要求是什么? KVC 将如何使用?
    • 我发现你的另一个问题可能激发了这个问题,并在那里发布了answer
    【解决方案2】:

    您还没有为要访问的键实现 setter 和 getter,也没有实现 -setValue:forUndefinedKey:

    在运行时,NSObject 的-setValue:forKey: 实现会查找名为“set1:”的方法,如果找不到,它会查找名为“1”的 ivar(这不是ivar,但仍然),如果失败,它会尝试发送 -setValue:forUndefinedKey:,但您尚未实现。

    阅读有关键值编码的文档,并了解如何使您的类符合 KVC。

    【讨论】:

      【解决方案3】:

      请阅读 Apple 文档中ensuring KVC compliance 中的部分。

      上面写着:

      对于属于属性或一对一关系的属性,这要求您的类:

      • 实现名为 -、-is 的方法,或具有实例变量 或 _
      • 如果属性是可变的,那么它也应该实现 -set:.

      合成一个属性也有资格实现一个方法,所以你的Universal类需要一个名为1(和2等)的方法和另一个名为set1:的方法,因为它肯定没有方法名称以数字开头是非法的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多