What is coding key values ​​and monitoring key values ​​in Objective-C?

Can someone explain in simple terms what Key-Value-Coding and Key-Value-Observing ? Do not include links to Apple Developer Help. I went through them. I expect an explanation in very simple terms.

+50
objective-c
Nov 26 '10 at 4:17
source share
4 answers

Key Value Encoding (KVC) means accessing a property or value using a string.

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

What could be the same:

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

Key-Value-Observing (KVO) allows you to observe changes in a property or value.

To observe a property using KVO, you must identify the property with a string; that is, using KVC. Therefore, the observed object must comply with KVC requirements.

 [myObject addObserver:self forKeyPath:@"foo.bar.baz" options:0 context:NULL]; 
+93
Nov 26 '10 at 4:52
source share

Key Value Coding is simply accessing an object of an object through a string instead of literal syntax.

 // 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"]; 

The power of KVC is that you can specify any arbitrary string at runtime (obviously this can be very dangerous too).

+24
Nov 26 '10 at 4:44
source share

The key value of the encoding allows you to retrieve or modify the property of an object using a string at run time instead of having to write code that compiles with a fixed property from the start:

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

A good example for this is NSTableView on a Mac, where you can simply set an identifier in each column of the table that matches your property of the model object that it should display, and then your data source simply calls -valueForKey: / - setValue: forKey: with identifier column as a key and values ​​are largely displayed / set by themselves. You simply add the correct columns to the table view in XIB.

After that, monitoring of key values ​​has been added and allows you to register to receive notifications of changes made to another object. You register your interest by doing:

 void* gMyKVOContext = &gMyKVOContext; // global variable somewhere that guarantees us a unique address that doesn't collide with a subclass registration for observing the same property ... [interestingObject addObserver: interestedObject forKeyPath: @"interestingProperty" options: 0 context: gMyKVOContext]; 

Whenever this property changes, -observeValueForKeyPath: ofObject: change: context: will be called on the object that you specified as an observer. Thus, you implement this as:

 - (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]; } 

The advantage here is that you receive a call in real time when another property changes. Note that objects should do a little work, so these notifications are sent, so not all properties are observable by keywords. Also note that some objects may be in an unacceptable state if two related properties change immediately after another: you receive a notification after the first property has been changed, which now contradicts the second, and only then the second property is changed, for which it is notified. Therefore, during the first observer callback, the object may be in a strange state, so be careful how you react to it.

To make a property observable, either use the standard @synthesized implementation when you define it, or define it yourself, configure, for example:

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

Then always go through the setter to change it, don't change _foo directly. If you have related properties that may conflict with each other, as mentioned above, a good way to avoid this is to always change them as in pairs (then you cannot use KVC). To do this, perform a combined setter, for example:

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

In this way, both notifications are sent while the properties are in the correct states.

+12
Apr 10 '14 at 9:38
source share

Start here.

The key value is the mechanism for accessing the properties of objects indirectly, using strings to define properties, and not by calling an access method or accessing them through instance variables.

+6
Nov 26 '10 at 5:32
source share



All Articles