Key-Value Coding

Objective-C lets you call methods specified by variables at runtime using the selector mechanism. Key-value coding is a library facility that puts field access on the same dynamic footing: you can access an object’s fields by naming them. For example, you could use the following code to retrieve the parent field of a window object:

Window*parentWind = [wind valueForKey:@"parent"];

Because you can pass a string variable to -valueForKey : as well as a literal value, this is another way your program’s behavior can vary based on values that aren’t known until runtime.

NSObject implements -valueForKey: method as part of the NSKeyValueCoding category, which declares methods for reading from and writing to the fields of objects. These methods store and retrieve Objective-C objects, so their primary use is in accessing objects. However, even if your fields are integers or other numeric types, you can still use key-value coding to retrieve and set them. The methods will take NSNumber objects and automatically convert them to set numeric fields, and return NSNumber objects when you read numeric fields.

Access Permissions

The key-value methods can bypass the access modifiers of the static language: you can read and write to private fields as easily as to public ones. This might seem like a violation of the object’s declared interface. However, you can prevent key-value methods from bypassing your access modifiers by overriding +accessInstanceVariablesDirectly to return NO.

In addition, the key-value methods first search for an appropriate accessor method in your class before attempting to read from or write to a field directly. For example, the methods that read a field named field will look for accessor methods with the following names (the order will vary as described in the next section):

  • getField

  • field

  • _getField

  • _field

The key-value methods will take care of uppercasing the first letter of the field name before prepending get or set.

Note

Although the key-value methods will search for methods or fields whose names start with an underscore, Apple has reserved these names for its internal use. Your classes should not have methods or fields that start with an underscore.

If your class provides accessor methods with the appropriate names, they will be called even if they are private methods not declared in your class’s interface.

NSKeyValueCoding Methods

The NSKeyValueCoding protocol declares (and NSObject implements) six methods that let your objects use key-value coding:

-(id)valueForKey:(NSString*)key

Given the name of a field, returns the value stored in that field. If key is "field", -valueForKey: tries the following ways to get the associated value:

  1. Calls -getField, if it exists.

  2. Calls -field, if it exists.

  3. Calls -_getField, if it exists.

  4. Calls -_field, if it exists.

  5. Reads field, if it exists and direct access is allowed.

  6. Reads _field, if it exists and direct access is allowed.

If all of these fail, -valueForKey: calls -handleQueryWithUnboundKey: on your object.

-(void)takeValue:(id)value forKey:(NSString*)key

Given the (pointer to the) object, this method stores the pointer to the object in the field of the receiver named by the key. If key is "field", -takeValue:forKey: tries the following ways to set the associated value:

  1. Calls -setField:, if it exists.

  2. Calls -_setField:, if it exists.

  3. Sets field, if it exists and direct access is allowed.

  4. Sets _field, if it exists and direct access is allowed.

If all of these fail, -takeValue:forKey: calls -handleTakeValue:forUnboundKey: on your instance.

- (id)storedValueForKey:(NSString*)key

Works like -valueForKey:, but with a possibly different search sequence:

  • If +useStoredAccessor returns NO, the sequence is the same as with -valueForKey:.

  • If +useStoredAccessor returns YES (the default behavior), this method starts searching in reserved accessors (ones starting with underscores) first.

For example, if key is "field", and +useStoredAccessor returns YES, -storedValueForKey: tries the following ways to get the associated value:

  1. Calls -_getField, if it exists.

  2. Calls -_field, if it exists.

  3. Reads _field, if it exists and direct access is allowed.

  4. Reads field, if it exists and direct access is allowed.

  5. Calls -getField, if it exists.

  6. Calls -field, if it exists.

If all of these fail, -storedValueForKey: calls -handleQueryWithUnboundKey: on your instance.

The alternative search sequence supported by -storedValueForKey: facilitates using key-value coding for storing and retrieving objects from a database, when you want to bypass public accessors that may have side-effects.

-(void)takeStoredValue:(id)value forKey:(NSString*)key

Works like -takeValue:forKey:, but with a possibly different search sequence:

  • If -useStoredAccessor return NO, the sequence is the same.

  • If +useStoredAccessor returns YES (the default behavior), this method starts searching in reserved accessors (ones starting with underscore) first.

For example, if the key is field, and +useStoredAccessor returns YES, -takeStoredValue:forKey: tries the following ways to get the associated value:

  1. Calls -_setField:, if it exists.

  2. Sets _field, if it exists and direct access is allowed.

  3. Sets field, if it exists and direct access is allowed.

  4. Calls -setField:, if it exists.

If all of these fail, -takeStoredValue:forKey: calls -handleTakeValue:forUnboundKey: on your object.

+(BOOL)accessInstanceVariablesDirectly

The NSObject version returns YES. Override this in your class to affect the search sequence for the basic methods -valueForKey: and -takeValueForKey:.

+(BOOL)useStoredAccessor

The NSObject version returns YES. Override this in your class to affect the search sequence for the stored methods -storedValueForKey: and -takeStoredValue:forKey:.

Handling Key Lookup Failures

The category NSKeyValueCodingExceptions provides three methods for handling failures in the lookup sequence and other problems:

-(id)handleQueryWithUnboundKey:(NSString*)key

Called when lookup fails for a getter (-valueForKey: or -storedValueForKey:) with the provided key. The default version of this method, provided in NSObject, raises an UnknownKeyException . Override this to handle things your way.

-(void)handleTakeValue:(id)value forUnboundKey:(NSString*)key

Called when lookup fails for a setter (-takeValueForKey: or -takeStoredValueForKey:) with the provided key. The default version of this method, provided in NSObject, raises an UnknownKeyException. Override this to handle things your way.

-(void)unableToSetNilForKey:(NSString*)key

Called when you pass nil in to a setter for a numeric field. NSObject’s version raises an exception. Override this in your class if there is a plausible numeric value (zero, or an out-of-band value) to use.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.70.185