In the last article, we studied the nature of objects through the source code compiled by Clang. In this article, we further analyze the class, or cut into the actual case.

The analysis of the class

We make a breakpoint when the object alloc, input the corresponding LLDB debugging instruction, and analyze the class by outputting the memory address. For details, please refer to the following

LLDB debugging command
X /nuf <addr> n Indicates the number of memory units to be displayed -------------------------- u indicates the length of an address unit. B indicates single byte. H indicates double bytes -------------------------- f indicates the display mode. The value can be: X displays variables in hexadecimal format d in decimal format U displays variables in decimal format unsigned integer o Displays variables in octal format T Displays variables in binary format A Displays variables in hexadecimal format I Instruction address format C Displays variables in character format F Displays variables in floating point formatCopy the code
Breakpoint debugging

When the breakpoint is at alloc, enter the LLDB instruction x/4gx p, and you can see the pointer address of the object output. The first address 0x011D800100008489 is the ISA pointer address of the object ATPerson. This paper takes x86_64 architecture as an example, 0x00007ffffffffff8ULL), and the result is 0x0000000100008488. The output result is ATPerson class through Po.

One more thought about the above output is that if we get the isa pointer to the class and&onISA_MASKAnd what was the result?

Based on the output above, we see that the result is stillATPerson, is the same as before, but the memory address of the second time is inconsistent, the address of the first time is0x0000000100008488And the second address is0x0000000100008460, belong toATPerson, but the address is not consistent, let’s write another function to verify:

Class class1 = [ATPerson Class]; void atTestClassNum(void) {Class Class [ATPerson Class]; Class class2 = [ATPerson alloc].class; Class class3 = object_getClass([ATPerson alloc]); Class class4 = [ATPerson alloc].class; NSLog(@"\n%p \n%p \n%p \n%p",class1,class2,class3,class4); Int main(int argc, const char * argv[]) {@autoreleasepool {atTestClassNum(); } return 0; }Copy the code

A printout

I get all of these0x100008488That’s the same thing as the first time up, the second time upATPersonWhat is it? According to the compiled executable (Products - > project name), use MachOView tool to analyze the symbol table and findSymbol Table ~> Symbols, search box inputclassYou can find a lot of information about classATPersonThe relevant position can be seen_OBJC_CLASS_$_ATPersonAnd there’s another one on top_OBJC_METACLASS_$_ATPersonThat’s the concept of objective-C metaclasses, which are automatically compiled by the system.

Based on the above debugging analysis, we can draw a simple conclusion: object ISA ~> class ISA ~> metaclass; Let’s take a closer look at class formation in two directions.

First, ISA is out of position

From the above analysis we explored object -> class -> metaclass, so a question? Do metaclasses have ISA? Where does the isa of that metaclass point if it exists? We explore the following questions in two directions:

Custom class

Then the above ATPerson continues to analyze

Print the address of the metaclass ATPerson at 10x0000000100008460, continue to execute x/4gx to get the metaclass isa as0x000000010036a0f0.&onISA_MASKYou get the root metaclass0x000000010036a0f0That’s the second oneNSObject, x/4gx and get isa(0x000000010036a0f0),&onISA_MASKAnd then you get the same result in the third position as in the second positionNSObject; So the line looks like this:

Object ISA ~> class ISA ~> metaclass ISA ~> root metaclass ISA ~> root metaclass.

NSObject class

Print the address of the NSObject root class is0x000000010036a140Gets the ADDRESS of the ISA pointer to NSObject0x000000010036a0f0The root metaclass address is the same as the root metaclass address. So the line is:The root class isa~ >A metaclass isa

Based on the above two directions of exploration, we have summarized the following isa trend chart.

The ISA of the object finds the class, the ISA of the class finds the metaclass, the ISA of the metaclass finds the root metaclass, and the ISA of the root metaclass finds itself.

Second, the chain of inheritance

Analyze class inheritance with the following code, executed and printed in the main function

ATTeacher inherits ATPerson, and ATPerson inherits NSObject

Void atTestNSObject(void) {// NSObject instance object NSObject *object = [NSObject alloc]; // NSObject Class Class = object_getClass(object); // NSObject metaClass = object_getClass(Class); // NSObject rootMetaClass Class rootMetaClass = object_getClass(metaClass); // NSObject rootMetaClass Class rootRootMetaClass = object_getClass(rootMetaClass); NSLog (@ "\ n \ n % p % p instance objects class p metaClass \ n \ n % % p root metaClass \ n % p spikes metaClass", object, class, metaClass, rootMetaClass, rootRootMetaClass); // Class pMetaClass = object_getClass(atPerson.class); Class psuperClass = class_getSuperclass(pMetaClass); NSLog(@"%@ - %p",psuperClass,psuperClass); Class tMetaClass = object_getClass(atteacher.class); // ATTeacher -> ATPerson -> NSObject Class tsuperClass = class_getSuperclass(tMetaClass); NSLog(@"%@ - %p",tsuperClass,tsuperClass); // NSObject Root Class special case Class nsuperClass = class_getSuperclass(nsobjject); NSLog(@"%@ - %p",nsuperClass,nsuperClass); // root metaClass -> NSObject Class = class_getSuperclass(metaClass); NSLog(@"%@ - %p",rnsuperClass,rnsuperClass); } int main(int argc, const char * argv[]) { @autoreleasepool { atTestNSObject(); } return 0; }Copy the code

Run the output

The following conclusions can be drawn from the operation result data:

  1. NSObject’s metaclass, root metaclass, and root metaclass are the same
  2. The parent of the ATPerson metaclass is the NSObject metaclass (0x7fff8079dfe0)
  3. The parent of the ATTeacher metaclass is the ATPerson metaclass
  4. The parent of the NSObject class is NULL
  5. The parent of the NSObject metaclass is the NSObject class (0x7fff8079e008)

Therefore, the following diagram can be obtained through inheritance analysis

conclusion

By analyzing objective-C classes from two different perspectives, isa orientation and inheritance chain to explore the class diagram, we combined the two situations into a diagram that is the class orientation diagram provided by Apple official documentation.

The isa of the class points to the metaclass, the ISA of the metaclass points to the root metaclass, and the ISA of the root metaclass points to itself. 2. From an inheritance perspective, subclasses point to the parent, and the parent points to the root class (NSObject). NSObject is nil; The subclass metaclass points to the parent metaclass, which points to the root metaclass, which points to the NSObject class.Copy the code