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 viewsetValueForKeyMethod to find it inFoundationThe inside. The Foundation framework is not open source, so go to apple’s official documentation.Key-Value Coding Programming GuideYou see it heresetValueForKeyThe process of the method is as follows:

  • Step 1: Find the name in orderset<Key>._set<Key>orsetIs<Key>The setter method for. Call it if you find it.
    • If you implement either one, it willCall this methodSet 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
  • Step 2: Check if none of the three setter methods are implementedaccessInstanceVariablesDirectlyWhether to returnYESIf 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 itA setter methodorThe instance variables, the system will execute the objectSetValue: forUndefinedKey:Method is thrown by defaultNSUndefinedKeyExceptionType 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 firstget<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 itcountOf<Key>.objectIn<Key>AtIndex:and<Key>AtIndexes:
    • If you findcountOf<Key>And one of the other two methods to create a collection proxy object that responds to all NSArray methodsNSKeyValueArrayAnd return the object. Otherwise it goes to step three.
    • The broker object then converts all received NSArray messages tocountOf<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.
  • Step 3: If the normal getter method or the array’s combined getter method is not implemented, then both getters are looked forcountOf<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 slimcountOf<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 likeNSSetEven if it’s not an NSSet.
  • Step 4: If you do not implement the normal getter method or the set’s combined getter method, andaccessInstanceVariableDirectlyreturnYES, 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 ismultiple,Gets the value of the instance variable in the previous order. Then go to step five
    • Otherwise, go to step six
  • 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 objectValueForUndefinedKey:Method is thrown by defaultNSUndefinedKeyExceptionType 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

  1. Check whether the key is empty

  1. To see if there issettermethodsset<Key>:._set<Key>.setIs<Key>, if so, implement and return.

3. The judgeaccessInstanceVariablesDirectlyIf 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