有人能简单地解释一下什么是Key-Value-Coding
和Key-Value-Observing
吗?请不要提供Apple Developer参考文档的链接。我已经看过了。我希望得到一个非常简单的解释。
发布于 2010-11-26 12:52:23
键值编码(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];
发布于 2010-11-26 12:44:04
键值编码只是通过字符串而不是文字语法访问对象的属性。
// 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的强大之处在于,您可以在运行时指定任意字符串(显然,这也可能非常危险)。
发布于 2014-04-10 17:38:56
键值编码允许您在运行时使用字符串获取或更改对象的属性,而不需要编写从一开始就编译为固定属性的代码:
NSNumber* foo = [myPopup valueForKey: @"selectedItemIndex"];
[myPopup setValue: @15 forKey: @"selectedItemIndex"];
一个很好的例子是Mac上的NSTableView,您只需在与模型对象的属性相对应的每个表列上设置一个标识符即可显示,然后您的数据源只需调用-valueForKey:/-setValue:forKey:,并将列的标识符作为关键字,值本身就会显示/设置。您只需将正确的列添加到XIB中的表视图中。
Key-value observing是后来添加的,它允许您注册以获得有关对另一个对象所做更改的通知。您可以通过执行以下操作来注册您的兴趣:
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];
}
这样做的好处是,当其他属性发生变化时,您就会被调用live。请注意,对象需要做一些工作才能发送这些通知,因此并不是所有属性都是键值可观测的。还要注意的是,如果两个相关的属性相继更改,则某些对象可能处于无效状态:第一个属性更改后,您会收到通知,这与第二个属性相矛盾,只有在第二个属性更改后,您才会收到通知。因此,在第一次观察者回调期间,对象可能处于奇怪的状态,因此要注意对此的反应。
要使属性可观察,请在定义该属性时使用默认的@synthesized实现,或者如果您自己定义该属性,则实现如下的setter:
-(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"];
}
这样,两个通知都会在属性处于正确状态时发送。
https://stackoverflow.com/questions/4282493
复制相似问题