The introduction of

As we know, classes can be added to add methods to a class, and you can define a variable via @property, but only the declaration of getter and setter methods for that variable is generated, no implementation of the method, and no underlined member variables. So the implementation of getter and setter methods needs to be implemented ourselves. We use Runtime to add associatedobject to the class, calling the two Runtime functions objc_setAssociatedObject and objc_getAssociatedObject. With two or two functions, you can store data for variables defined in a class into a table of associated objects of the class. So how is it stored and evaluated?

Storage analysis

We analyze this with an objC4-781 source code

Objc_setAssociatedObject Low-level call

Setassocook.get () is a call to a function pointer that actually calls the function _base_objc_setAssociatedObject

_base_objc_setAssociatedObject calls the _object_set_associative_reference function

That is, objc_setAssociatedObject actually calls _object_set_associative_reference, so why have so many calls in between? First, it is convenient to carry out more Settings later, and second, it can be more flexible to call different Settings in multiple places.

_object_set_associative_reference analysis

  • DisguisedPtr<objc_object> disguised{(objc_object *)object};Wrap objcet into oneDisguisedPtr
  • ObjcAssociation association{policy, value};Store policypolicyandvalueThe value is wrapped into oneObjcAssociation

The acquireValue function is the processing under different storage policies

  • rightOBJC_ASSOCIATION_SETTER_RETAINforobjc_retain;

AssociationsManager is an associated object management class

  • inThe constructorandThe destructorAdd a lock to preventMultithreaded repeat creationAs a result of theHashMapRepeated operation of

AssociationsHashMap is a global HashMap table that stores associated objects

  • 1.AssociationsHasMapThe structure of theDisguisedPtrFor the key andObjcetAssociationMapFor the value ofKey/value pair;
  • 2.AssociationsHashMapIs through theAssociationsManagerthegetFunction created;
  • 3.static Storage _mapStorageTo ensure theAssociationsHashMapIs globally unique.

  • valueIf it does, it goes through the functiontry_emplaceAccording to the assembleddisguisedGo to theA hashMap tableInsert into table;
  • valueIf not, pass the functionfindAccording to the assembleddisguisedGo to theA hashMap table, and then erase the original records from the table.

  • If no BucketT is found, return an empty BucketT for external callers to set the new value.
  • New value found for return external caller setting.

Associated object structure

AssociationsHashMap is a HashMap table using DisguisedPtr as key and ObjectAssociationMap as Value. Each class using the associated object is inserted into the HashMap. ObjectAssociationMap is a Map table whose key is const void* and whose value is ObjcetAssociation. Associated objects of instances of classes that use associated objects are stored in this Map table.

Set the value process summary

    1. To create aAssociationsManagerManagement class;
    1. Gets a unique global staticHashMap;
    1. Check whether the inserted correlation value exists:
(1) Existence goes to step 4; (2) do not exist to go: 'associated object insert empty process';Copy the code
    1. Create an emptyObjectAssociationMapTo fetch the key-value pair of the query;
    1. If you don’t have thiskeyI just insert an empty oneBucketTGo in, go back;
    1. tagObject has an associated object;
    1. With the currentStorage policyandvalueMake up aObjcAssociationReplace the originalBucketTThe empty;
    1. Mark theObjectAssociationMapFor the first timefalse.

The associated object inserts an empty process

    1. According to theDisguisedPtrfindAssociationsHashMapIn theiteratorIterating query;
    1. Clean iterators;
    1. In fact, if you insert empty is equivalent to clearing.

Value analysis

Objc_getAssociatedObject analysis

_object_get_associative_reference analysis

  • createAssociationsManagerAnd find globally uniqueAssociationsHashMap;
  • According to theDisguisedfindAssociationsHashMapThe iteratoriterator;
  • findobjcettheObjectAssociationMap;
  • According to thekeyTo find ObjectAssociationMapIn thevalueAnd return.

Summary of Value Selection Process

  • 1. Create oneAssociationsManagerManagement class;
  • 2. Get a unique global staticHashMap;
  • 3. According toDisguisedPtrfindAssociationsHashMapIn theiteratorIterating query;
  • 4. If the iterated query is not the last, getObjectAssociationMap(Storage policy and value);
  • Find 5.ObjectAssociationMaptheIterated queryGets a value modified by an attribute modifier;
  • 6. Return_value.

conclusion

From the analysis of the storage value of the associated object, it can be seen that the associated object actually maintains a two-layer hash Map table.