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 – aboutruntimeImproved 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. ByclangCompile 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_setPropertymethods

2. The positioninggetSetPropertyFnmethods

3. The positioningGetPropertySetFunctionmethods

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. PropertyImplStrategyThe 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_getPropertymethods

2. The positioninggetGetPropertyFnmethods

3. The positioningGetPropertyGetFunctionmethods

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 metaclassClass methodYou can also getClass method? (Proved:Class methodObject methodsForm stored inThe metaclassC)

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:

  • re1NSObjectcall+ isMemberOfClass:NSObjectComparison. soNSObject metaclasswithNSObjectIt’s not equal, so it’s 0.
  • re3ZLObjectcall+ isMemberOfClass:ZLObjectComparison. soZLObject metaclasswithZLObjectIt’s not equal, so it’s 0.
  • re5NSObject objectcall- isMemberOfClass:NSObjectComparison. soNSObject objectThe class isNSObject, andNSObjectIt’s the same thing, so it’s 1.
  • re7ZLObject objectcall- isMemberOfClass:ZLObjectComparison. soZLObject objectThe class isZLObject, andZLObjectIt’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:

  • re2NSObjectClass, getThe metaclassNSObjectNo, keep looking for accessThe superclass of the metaclassNSObjectNSObjectIf yes, return 1.
  • re4ZLObjectClass, getThe metaclassZLObjectNo, keep looking for accessThe superclass of the metaclassNSObject metaclassStill unequal. Keep going upThe superclass of the NSObject metaclassNSObjectStill not. It’s just up therenil, and return 0.
  • re6NSObject objectTo obtainclassNSObjectWhich is equal to NSObject and returns 1.
  • re8ZLObject objectTo obtainclassZLObjectWhich is equal to NSObject and returns 1.