preface
Following the exploration of the underlying principles of classes (I), you have understood the STRUCTURE of ISA Pointers and classes. Let’s continue to explore the underlying principles of classes and supplement them accordingly.
The preparatory work
WWDC – aboutruntime
Improved optimization of
LLVM source
The underlying principle of member variables
When analyzing the underlying principles of the class (I), only properties and methods were analyzed.
Properties and methods are in class_rw_t.
The member variable ivars is found in ro() of class_rw_t, which is class_ro_t.
The class_ro_t structure is as follows:
Case a
By analyzing the case of IVars, add the following code:
Print result:
At this point, ivars are present in ivar_list_t, and each member variable is obtained using the C++ array get().
The difference between member variables, attributes, and instance variables
Member variable A variable declared as a basic data type in a class {}, such as NSString, int, float, double, char, bool.
Properties are decorated with @property, which underneath become _ member variables, and get and set methods are automatically generated. Attribute = _ member variable + set + GET
Instance variables are declared as object types (special member variables), such as NSObject *p, where p is an instance variable.
Case 2
1. Create oneProject
, add the following code:
2. Byclang
Compile and view the compiled file:
$ clang -rewrite-objc main.m -o main.cpp
Property becomes a member variable of _ when compiled, and the corresponding set and get methods are generated.
But the set implementation is different:
Name is implemented using the objc_setProperty method
Address and age are stored as memory address offsets
Why is it different? Name is a copy modifier, presumably related to the copy modifier.
Analysis objc_setProperty
Why does objc_setProperty exist?
When a property is created and a set is called, it is not possible to generate a corresponding set method in the underlying layer for every property that is created. This would be too expensive for memory. So we have the objc_setProperty method, and whatever set method is on top of it, we call the objc_setProperty method. This process is called SEL → IMP.
SEL is the method name, and IMP is the underlying method implementation.
Since objc_setProperty is created directly at compile time, you need to look in the LLVM source code for objc_setProperty.
1. The positioningobjc_setProperty
methods
2. The positioninggetSetPropertyFn
methods
3. The positioningGetPropertySetFunction
methods
The GetPropertySetFunction method is called, In the switch selection strategy. GetKind () for PropertyImplStrategy: : GetSetProperty or PropertyImplStrategy: : SetPropertyAndExpressionGet execution.
So what does strategy mean? When do you assign a value to it? What does each case mean?
Analysis of 4.PropertyImplStrategy
5. PropertyImplStrategy
The constructor
Conclusion:
As long as copy is set, atomicity or not, it doesn’t matter, the set method is redirected to objc_setProperty.
If no property is set (other than atomicity), then the default property is strong and the objc_setProperty does not trigger.
Analysis objc_getProperty
Objc_getProperty also needs to be looked up in the LLVM source code.
1. The positioningobjc_getProperty
methods
2. The positioninggetGetPropertyFn
methods
3. The positioningGetPropertyGetFunction
methods
The underlying principles of class methods
The LLDB verification process is as follows:
Conclusion:
Object methods are stored in their own classes
Class methods are stored in the metaclass and exist in the metaclass as object methods.
There is no such thing as class methods. All methods are object methods, with functions at the bottom.
Supplementary: TypeEncoding
In main.cpp above, a search for setName reveals some strange symbols.
“v24@0:8@16” and “@16@0:8” are actually type codes. So let’s look at what type encoding is.
TypeEncoding It boils down to analyzing the code against the symbol table below.
Then take the above setName as an example to analyze the practical significance of v24@0:8@16.
Supplement: interview questions
1. WhyThe metaclass
的 Class method
You can also getClass method
? (Proved:Class method
以 Object methods
Form stored inThe metaclass
C)
The print result is as follows:
Analysis of the underlying method:
The analysis shows that the so-called class method is actually the object method to obtain the metaclass.
Analyze the getMeta() method:
If it isa metaclass, return the metaclass itself, otherwise return the metaclass isa. This is why a class method that gets a metaclass can also get a class method.
2. About isKindOfClass
Case study:
Print result:
IsMemberOfClass and isKindOfClass methods are found in the source code.
But during execution, the isKindOfClass method is not executed, only the isMemberOfClass method is executed. So let’s look at isMemberOfClass
isMemberOfClass
Analyze the source code as follows:
+ isMemberOfClass: is to get the class metaclass to compare with the class
-isMemberofClass: Indicates that the class object is obtained for comparison with the class
Analyze the code above:
re1
是NSObject
call+ isMemberOfClass:
与NSObject
Comparison. soNSObject metaclass
withNSObject
It’s not equal, so it’s 0.re3
是ZLObject
call+ isMemberOfClass:
与ZLObject
Comparison. soZLObject metaclass
withZLObject
It’s not equal, so it’s 0.re5
是NSObject object
call- isMemberOfClass:
与NSObject
Comparison. soNSObject object
The class isNSObject
, andNSObject
It’s the same thing, so it’s 1.re7
是ZLObject object
call- isMemberOfClass:
与ZLObject
Comparison. soZLObject object
The class isZLObject
, andZLObject
It’s the same thing, so it’s 1.
isKindOfClass
In the above case, isKindOfClass is not executed, only isMemberOfClass related methods are executed. What is the reason for this?
The reason isKindOfClass is not executed is because objc_opt_isKindOfClass is executed underneath.
To analyze objc_opt_isKindOfClass:
In the above code, whether + isKindOfClass: or -isKindofclass: is called from the upper layer, the internal redirection is to the objc_opt_isKindOfClass method. Because a class is essentially an object, we call it a class object. So obj has a value every time.
Analyze the source code as follows:
If it is a class: first get the class’s metaclass and compare it with the class. Returns true if they are equal. If not, then get the parent of the class and compare it with the class. Equality returns true. Otherwise, loop through the parent class and compare it to the class until you get a parent class that is nil. If you still don’t find it, return false.
In the case of instance objects, first get a class-to-class comparison. Returns true if they are equal. Otherwise the steps are the same as for the class.
Analyze the code above:
re2
是NSObject
Class, getThe metaclass
与NSObject
No, keep looking for accessThe superclass of the metaclass
为NSObject
与NSObject
If yes, return 1.re4
是ZLObject
Class, getThe metaclass
与ZLObject
No, keep looking for accessThe superclass of the metaclass
为NSObject metaclass
Still unequal. Keep going upThe superclass of the NSObject metaclass
为NSObject
Still not. It’s just up therenil
, and return 0.re6
是NSObject object
To obtainclass
为NSObject
Which is equal to NSObject and returns 1.re8
是ZLObject object
To obtainclass
为ZLObject
Which is equal to NSObject and returns 1.