This is the 16th day of my participation in the August More Text Challenge
1. Check whether sorting is required for category loading
As you know from the previous article, in the method list, the array Pointers of the two classes of methods precede the main class, and the array Pointers are sorted. First add two categories, and both classes have a method called testFunc1. Run and see getMethodNoSuper_nolock. You can see that this is traversal search.
The output sees beginLists are classified LS.
Array_t holds three 2-dimensional Pointers that don’t need to be sorted; they each have their own sort. Fetching methodList does a traversal lookup, which also shows that class loads don’t require sorting. What about the need to probe during the 2-minute search? Because methods are integrated when classes and categories are read in the data segment, probe is needed to find the first method.
2. Data structure for methodList
The data structure for methodList is method_list_t, inherited from entsize_list_TT.
As you know from the previous article, methodList is stored as a pointer.
When retrieving an element, you need to call get to retrieve it, which means that method_list_t holds Pointers instead of values, otherwise it could be fetched as an array. And the pointer points to method_t.
In view of the get method, it can be seen that the get method obtains the pointer address through address translation.
3. The load method is not implemented by the main class, so the data load is implemented by the classification method
What happens when the main class doesn’t implement a load method? Create 3 categories, 2 of which have methods and attributes, and the other one does not. In a class that has methods and attributes, select one that implements the Load method. The main class is not lazily loaded, but the classes are not loaded.
Both classes implement the load method, and when run, you can see that the classes are loaded.
It can be concluded that when two or more categories implement the load method, then the categories will be loaded non-lazily. When viewing attachCategories, cats_count is 2. Which category is not loaded?
Output to see which categories are not loaded. Here we see that LS and LSS are loaded, LSSS is not loaded, which means that the system has been optimized. When there is nothing in the classification, it will not be loaded and waste performance.
When you see load_images, it goes prepare_load_methods instead of the normal loadAllCategories method. Prepare_load_methods, which is where the main class is forced to implement,
If you look at the implementation of prepare_load_methods, it does allow the main class to be non-lazily loaded, forcing the main class to open.
4.class_ro_t
Take a look at class_ro_t in LLVM.
So if you see a read here, look for a read. See read inside the address processing, and then get extractor, and then carry out each attribute assignment.
5. Class extends
Classification: categoty
- Used specifically to add new methods to classes.
- You cannot add member attributes to a class, nor can you retrieve member variables, but you can add attributes to a class via the Runtime.
- Classes that use @property to define variables only generate getters and declarations of setter methods, not method implementations and underlined member variables.
Extension: the extension
- Special categories, also called anonymous categories.
- You can add member attributes to a class, but as private variables.
- You can add methods to a class, which are also private.
So that’s an extension, and it has to be defined between at sign interface and at sign implementation.
clang
Open it by clicking main.m. Discover that extension methods and properties already exist
Will class extensions have their own structure, like classifications? I looked around and found none. Classification affects class loading, but does extension? Add a class extension to LGPerson and add methods, and then add the implementation of the method to LGPerson. LGPerson implements load, hits a breakpoint at realizeClassWithoutSwift and runs it. Run it and print ro’s list of methods in realizeClassWithoutSwift and then look and see that the class extension has been loaded. That is, when the class is loaded, the class extension is already loaded as part of the class.
6. Associated objects
The realization of the underlying principle of the associated object is mainly divided into two parts:
- through
objc_setAssociatedObject
Set the value process - through
objc_getAssociatedObject
Value of the process
Override the set and get methods of attributes cate_namet and cate_age in the classification LGA via the Runtime attribute association methods objc_setAssociatedObject and objc_getAssociatedObject.
Associated object setting process
Look at the concrete implementation of objc_setAssociatedObject. This design pattern is the interface pattern, in which the external interface does not change, that is, external calls always call objc_setAssociatedObject, and internal logical changes do not affect external calls.
Then go to the _object_set_associative_reference. You see there are four parameters here.
- Objc: The object to associate, that is, to whom to add the associated attribute
- Key: indicates the identifier for next search
- Value: indicates the value to be saved
- Policy: indicates the association policy
Looking down, you see that object has been processed.
Click in the disguise method to check the PTR processing, that is, the processing of parameters, so here is the object packaging, packaging into a unified data structure.
At the bottom is objcasation Association {policy, value}.
Const void star is the name of the property, cate_name, cate_age, key value match. In AssociationsHashMap, different objects also correspond to different AssociationsMaps, so it is a double-layer HashMap structure.
Run the program to go to _object_set_associative_reference.
So let’s print out that’s exactly what we set.
Where AssociationsManager Manager is a constructor. Write a copy to make it easier to understand.
After the run found the output KC came up and masterclass NB.
So AssociationsManager is equivalent to calling AssociationsManager() and ~AssociationsManager().
AssociationsHashMap is a singleton and unique table, because _mapStorage is a static variable.
_object_set_associative_reference: ‘associations’ =’ associations’;
Refs_result = second = true = isFirstAssociation = true = it’s the first association we make That is, isFirstAssociation is set to true for the first association.
Refs_result is come from associations. Try_emplace (backup, ObjectAssociationMap{}). Take a look at the try_emplace method. I’m going to create a new bucket, and the key here is the address of LGPerson.
The first thing I do is go into LookupBucketFor to see if there is a bucket and I see two implementations, because in try_emplace BucketT has no const, so I go to the following implementation. The implementation below calls the implementation above.
If you look at the implementation above, this is where you get the index of the hash.
Then you go down into the loop and you find the bucket, and if you don’t find it, you hash it.
When first entered, LookupBucketFor(Key, TheBucket) could not be found, so went below. Here, an empty bucket was inserted, and the operation was expanded by 3 quarters and 2 times.
And then you get TheBucket
_object_set_associative_reference goes down and enters try_emplace again.
LookupBucketFor(Key, TheBucket) is still not inserted because there is nothing inside TheBucket yet. LookupBucketFor also returns false if TheBucket is empty.
And then we’re going to go to InsertIntoBucket, and then inside InsertIntoBucket we’re going to insert first
Print result in _object_set_associative_reference and find the value in first.
The PTR inside first is the bucket we put in.
When an empty value is passed, the bucket is cleared.
Associated object: Set value process summary
1: Create an AssociationsManager management class 2: obtain a unique global static hash Map 3: check whether the inserted association value exists. 3.1: Exists. Go to Step 4. Create an empty ObjectAssociationMap to fetch the query’s key-value pair. 5: Insert an empty BucketT if the key is not found. Replace the empty 8 in BucketT with an ObjectAssociation consisting of the current decoration policy and value: mark ObjectAssociationMap as false for the first time
The associated object inserts an empty process summary
1: According to the DisguisedPtr, the Iterator in AssociationsHashMap is found. 2: the iterator is cleared. 3: actually, if the DisguisedPtr is inserted vacant, it is equivalent to the clearance
Flow chart of associated objects.
Image from link: style_month.