什么是目标C中的键值编码和键值观察?

时间:2010-11-26 04:17:09

标签: objective-c

有人可以用简单的术语解释什么是Key-Value-CodingKey-Value-Observing?请不要提供Apple Developer参考文档的链接。我经历过他们。我希望用非常简单的术语来解释。

5 个答案:

答案 0 :(得分:116)

键值编码(KVC)表示使用字符串访问属性或值。

id someValue = [myObject valueForKeyPath:@"foo.bar.baz"];

可能与以下内容相同:

id someValue = [[[myObject foo] bar] baz];

键值观察(KVO)允许您观察属性或值的更改。

要使用KVO观察属性,您可以使用字符串标识属性;即,使用KVC。因此,可观察对象必须符合KVC。

[myObject addObserver:self forKeyPath:@"foo.bar.baz" options:0 context:NULL];

答案 1 :(得分:28)

键值编码只是通过字符串而不是文字语法访问对象的属性。

// Here is a new instance of an object
Foo *foo = [[Foo alloc] init];
// Accessing a property called someValue with literal syntax:
[foo someValue];
// Accessing the same property with dot notation
foo.someValue;
// Accessing the same property with Key-Value coding:
[foo valueForKey:@"someValue"];

KVC的强大之处在于你可以在运行时指定任意字符串(显然这也可能非常危险)。

答案 2 :(得分:12)

键值编码允许您在运行时使用字符串获取或更改对象的属性,而不是需要编写从一开始就编译为固定属性的代码:

NSNumber* foo = [myPopup valueForKey: @"selectedItemIndex"];
[myPopup setValue: @15 forKey: @"selectedItemIndex"];

这方面的一个很好的例子是Mac上的NSTableView,您可以在每个表列上设置一个标识符,该标识符对应于它应该显示的模型对象的属性,然后您的数据源只调用-valueForKey: / -setValue:forKey:将列的标识符作为键,值几乎显示/设置自己。您只需将正确的列添加到XIB中的表视图中。

之后添加了键值观察,并允许您注册以获得有关对另一个对象所做更改的通知。您可以通过以下方式注册您的兴趣:

void*    gMyKVOContext = &gMyKVOContext; // global variable somewhere that guarantees us a unique address that doesn't collide with a subclass's registration for observing the same property

...

[interestingObject addObserver: interestedObject forKeyPath: @"interestingProperty" options: 0 context: gMyKVOContext];

每当更改该属性时,-observeValueForKeyPath:ofObject:change:context:将在您指定为观察者的对象上调用。所以你要实现它:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if( context == gMyKVOContext && [keyPath isEqualToString: @"interestingProperty"] )
    {
        // Update UI that shows interestingProperty
    }
    else
        [super observeValueForKeyPath: keyPath ofObject: object change: change context: context];
}

这里的优势在于,您可以在其他属性发生变化时立即调用。请注意,对象必须执行一些操作才能发送这些通知,因此并非所有属性都是键值可观察的。另请注意,如果两个相关属性一个接一个地更改,则某些对象可能处于无效状态:在第一个属性发生更改后会收到通知,这现在与第二个属性相矛盾,并且只有第二个属性发生更改并且您&# 39;重新通知。因此,在第一个观察者回调期间,对象可能处于奇怪的状态,所以要小心你对此的反应。

要使属性可观察,请在定义属性时使用默认的@synthesized实现,或者如果您自己定义它,请实现以下设置器:

-(void)  setFoo: (int)inFoo
{
    [self willChangeValueForKey: @"foo"];
    _foo = inFoo;
    [self didChangeValueForKey: @"foo"];
}

然后总是通过setter来改变它,不要直接改变_foo。如果你有相关的属性可能会像上面那样相互矛盾,那么避免这种情况的一个好方法就是总是成对地改变它们(然而你不能使用KVC)。为此,请实现一个组合的setter,如:

-(void) setFoo: (int)inFoo bar: (int)inBar
{
    [self willChangeValueForKey: @"foo"];
    [self willChangeValueForKey: @"bar"];
    _foo = inFoo;
    _bar = inBar;
    [self didChangeValueForKey: @"bar"];
    [self didChangeValueForKey: @"foo"];
}

这样,两个通知都会在属性处于正确状态时发送。

答案 3 :(得分:7)

Start here.

  

键值编码是一种机制   访问对象的属性   间接地,使用字符串来识别   属性,而不是通过   调用访问器方法或   直接访问它们   实例变量。

答案 4 :(得分:0)

Objective-C 键值编码(KVC)与键值观察(KVO)

[Swift KVC]

KVC 允许您通过为所有 NSObject 继承者启用的 String 访问属性。它为语言增添了活力。您可以将您的课程视为 Dictionary(Key-Value)。这是分配/读/写变量的替代/非直接解决方案

[valueForKey vs valueForKeyPath]

B *b = [a valueForKeyPath:@"b"];

KVCKVO 以及 CoreData、Cocoa 绑定使用...

KVO 允许您订阅更改的值。它适用于动态调度

someClass.observe(\.v, options: .new) { (object, change) in
    //logic
}

[KVO example]