This is the 14th day of my participation in the August More Text Challenge. For details, see:August is more challenging
Key-value Coding is a mechanism enabled by the informal NSKeyValueCoding protocol that an object uses to provide indirect access to its attributes. You can access a property through a string key. This concise access mechanism complements the direct access provided by instance variables and their associated query methods.
1. The KVC set value
In general, there are two ways to assign an object property.
- Assign directly through the setter method
- Related API assignments encoded by KVC key values
To viewsetValueForKey
Method to find it inFoundation
The inside. The Foundation framework is not open source, so go to apple’s official documentation.Key-Value Coding Programming GuideYou see it heresetValueForKey
The process of the method is as follows:
- Step 1: Find the name in order
set<Key>
._set<Key>
orsetIs<Key>
The setter method for. Call it if you find it.- If you implement either one, it will
Call this method
Set the value of the property to the value passed in.If there are more than one, the one in the first order is called
. - If not, go to step two
- If you implement either one, it will
- Step 2: Check if none of the three setter methods are implemented
accessInstanceVariablesDirectly
Whether to returnYES
If yes, look for the name in order_<Key>
._is<Key>
.<Key>
oris<Key>
Instance variable. Otherwise, skip to step three.- As soon as any one is found, the instance variables will be assigned, or if there are more than one, the one in the first order.
- If not, go to step three.
- Step 3: If you can’t find it
A setter method
orThe instance variables
, the system will execute the objectSetValue: forUndefinedKey:
Method is thrown by defaultNSUndefinedKeyException
Type of exception.
The flow chart of setValueForKey
2. KVC values
The value method of KVC is valueForKey:, and the process is as follows:
- Step 1: Do it first
get<Key>
.<Key>
.is<Key>
._<Key>
In order to find the getter method- If so, go to step 5
- If not, go to step two
- Step 2: If the getter method is not implemented, KVC looks for it
countOf<Key>
.objectIn<Key>AtIndex:
and<Key>AtIndexes:
- If you find
countOf<Key>
And one of the other two methods to create a collection proxy object that responds to all NSArray methodsNSKeyValueArray
And return the object. Otherwise it goes to step three. - The broker object then converts all received NSArray messages to
countOf<Key>
.objectIn<Key>AtIndex:
and<Key>AtIndexes:
Some combination of messages that are sent to the key-value encoding object that created it. If the original object also implements a name calledget<Key>:range:
Proxy objects will also use this method when appropriate. In fact, the proxy object works with the key-value encoding object so that the property can be used like an NSArray, even if it is not an NSArray.
- If you find
- Step 3: If the normal getter method or the array’s combined getter method is not implemented, then both getters are looked for
countOf<Key>
.enumeratorOf<Key>
andmemberOF<Key>
These three methods- If all three methods are found, create a collection proxy object that responds to all NSSet methods and returns it. Otherwise, go to Step 4
- The proxy object then converts any NSSet it receives into a slim
countOf<Key>
.enumeratorOf<Key>
.memberOf<Key>
Send a message to the object that created it. In fact, proxy objects work with key-value encoding objects to make properties likeNSSet
Even if it’s not an NSSet.
- Step 4: If you do not implement the normal getter method or the set’s combined getter method, and
accessInstanceVariableDirectly
returnYES
, the instance variables will be looked for in order_<Key>
._is<Key>
.<Key>
oris<Key>
- As soon as you find one, you get the value of the instance variable and go to step five. If there is
multiple
,Gets the value of the instance variable in the previous order
. Then go to step five - Otherwise, go to step six
- As soon as you find one, you get the value of the instance variable and go to step five. If there is
- Step 5: Return the result
- If the property value searched is an object pointer, simply return the result.
- If the value is a variable type supported by NSNumber, store it in an NSNumber instance and return the object
- If the result is a variable type that NSNumber does not support, convert it to an NSValue object and return that object
- Step 6: If the above five methods fail, the system will execute the object
ValueForUndefinedKey:
Method is thrown by defaultNSUndefinedKeyException
Type of exception
The flow chart of valueForKey
3. Customize KVC
After looking at the set value and value, we can customize the implementation of KVC according to the official search rules given by Apple
3.1 User-defined Settings
- Check whether the key is empty
- To see if there is
setter
methodsset<Key>:
._set<Key>
.setIs<Key>
, if so, implement and return.
3. The judgeaccessInstanceVariablesDirectly
If YES, go down; otherwise, raise an exception.
4. Check whether the ivAR list contains instance variables_<Key>
._is<Key>
.<Key>
.is<Key>
, and assign a value when found
5. If none are found, an exception is thrown
3.2 User-defined Values
1. Check that the key is not null
2. Search in order:get<Key>
.<Key>
.countOf<Key>
.objectIn<Key>AtIndex
3. Determine whether accessInstanceVariablesDirectly return values to YES, you can go down, or throw an exception.
4. Check whether the ivAR list contains instance variables_<Key>
._is<Key>
.<Key>
.is<Key>
, and assign a value when found
5. Throw an exception
4. Application scenario
4.1 Dynamic Setting and Values
- Read and store via Key:
setValue:forKey:
andvalueForKey:
- Read and store via keyPath:
setvalue:forKeyPath:
andvalueForKeyPath:
4.2 Accessing and Modifying private variables through KVC
In daily development, private properties of a class are not directly accessible to objects defined externally. But with KVC, an object has no privacy of its own, so any private properties can be modified and accessed through KVC
4.3 Multi-value Operations
Model dictionary transformation
/ / dictionary model - (void) setValuesForKeysWithDictionary: (NSDictionary keyedValues < > nsstrings *, id *); / / model dictionary - (NSDictionary < > nsstrings *, id *) dictionaryWithValuesForKeys: (NSArray keys < > nsstrings * *);Copy the code
4.4 Modifying some internal properties of the system space
As an example, KVC can provide an easy solution to the problem: customize tabbar as an empty query when an empty query is an empty query in an empty query field. When an empty query is an empty query, an empty query is required as an empty query. When an empty query is an empty query, an empty query is required as an empty query
4.5 Implementation of high-level message passing with KVC
When using KVC on a container, valueForKey: will be passed to each object in the container instead of operating on the container itself, and the result will be added to the returned container, making it easy to operate on a set and return another set