By analyzing the nature of the object, we know that the ISA of the instance object points to the class object. Then we will analyze the isa process.

1. LLDB explores ISA

Define a SHPerson object that is initialized in the main function and debugged with a breakpoint.

The LLDB output is as follows:

  • The first print ispersonMemory distribution, and0x000021a1000080e9(isa) & 0x0000000ffffffff8ULL,persontheisaThe memory address pointed to is0x00000001000080e8And calledSHPersonClass object.
  • The second print is the memory distribution of the class object, and0x00000001000080c0(isa) & 0x0000000ffffffff8ULL, the obtained memory address is0x00000001000080c0, Po prints the result namedSHPersonThe calSS object of.
  • Compare the first and second prints, the two are respectively0x00000001000080e8and0x00000001000080c0The name of the printed class object is the same.
  • The third time is printing0x00000001000080c0Memory distribution, and0x00000001003790f0(isa) & 0x0000000ffffffff8ULL, the obtained memory address is0x00000001003790f0, Po prints the result namedNSObjectThe calSS object of.
  • Comparing the previous two prints, I found that they were different.0x00000001003790f0and0x00000001000080e8,0x00000001000080c0The printed class object names are different.
  • The fourth time is printing0x00000001003790f0The memory distribution of this discoveryisaThat it should be the same as it is0x00000001003790f0theisaIt’s pointing to itself.

Next, the three memory addresses will be studied:

0x00000001000080e8
0x00000001000080c0
0x00000001003790f0
Copy the code

Of course, this memory address is subject to change, you need to print the LLDB according to the breakpoint.

Look at the symbol table, deduce the class object, metaclass object, root metaclass object.

Open the code’s executable file (exec) with MachOView.

Locate the symbol table and scroll to the tawny section.

0x00000001000080e8 = 0x00000001000080E8 = 00000001000080C0 = 0x00000001000080E8 = 00000001000080C0 0x00000001000080C0 is a metaclass object, so what is 0x00000001003790f0? 0x00000001003790F0 is something called a root metaclass object.

The summary is as follows:

The ISA of the instance object points to the class object, the ISA of the class object points to the metaclass object, the ISA of the metaclass object points to the root metaclass object, and the ISA of the root metaclass object points to itself.

Class object, metaclass object, root metaclass object inheritance chain

Do class objects, metaclass objects, root metaclass objects also have inheritance chains? If so, what is the chain of succession? Add a SHStudent class inherited from SHPerson.

SHStudent is a subClass, SHPerson is a superClass, and NSObject is a rootClass.

1. Runtime API introduction.

Import the # import < objc/runtime. H >

  • object_getClass: Passes an object and returns its class object.
  • class_getSuperclass: Passes a class and returns the parent of the class.
  • objc_getClass: Passes a class name and returns the corresponding class object.
  • objc_getMetaClass: Passes a class name and returns the corresponding metaclass object.

Objc_getClass and objc_getMetaClass will be used first, because object_getClass can get class objects, metaclass objects, and root metaclass objects, as well as more runtime API documentation. The following explorations focus on object_getClass and class_getSuperclass.

2. Use the Runtime API to print output

     //1. Subclass instance object ISA flow and inheritance chain.
     NSLog(@"Subclass (SHStudent) print");
     SHStudent *student = [[SHStudent alloc] init];
     / / class object
     Class class_student = object_getClass(student);
     / / object metaclass
     Class metaclass_student = object_getClass(class_student);
     / / rootMetaclass object
     Class rootMetaclass_student = object_getClass(metaclass_student);
     
     NSLog(@"class_student : %@ - %p",class_student, class_student);
     NSLog(@"metaclass_student : %@ - %p",metaclass_student, metaclass_student);
     NSLog(@"rootMetaclass_student: %@ - %p",rootMetaclass_student, rootMetaclass_student);
     
     NSLog(@"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
     
     // The superclass object of the class object
     Class superclass_student = class_getSuperclass(class_student);
     // Superclass object of the metaclass object
     Class superMetaclass_student = class_getSuperclass(metaclass_student);
     // Superclass object of the rootMetaclass object
     Class superRootMetaclass_student = class_getSuperclass(rootMetaclass_student);
     
     NSLog(@"superclass_student : %@ - %p",superclass_student, superclass_student);
     NSLog(@"superMetaclass_student : %@ - %p",superMetaclass_student, superMetaclass_student);
     NSLog(@"superRootMetaclass_student: %@ - %p",superRootMetaclass_student, superRootMetaclass_student);
     
     //2. Isa flow and inheritance chain for instance objects of the parent class.
     NSLog(@"");
     NSLog(@"SHPerson prints");
     SHPerson *person = [[SHPerson alloc] init];
     / / class object
     Class class_person = object_getClass(person);
     / / object metaclass
     Class metaclass_person = object_getClass(class_person);
     / / rootMetaclass object
     Class rootMetaclass_person = object_getClass(metaclass_person);
     
     NSLog(@"class_person : %@ - %p",class_person, class_person);
     NSLog(@"metaclass_person : %@ - %p",metaclass_person, metaclass_person);
     NSLog(@"rootMetaclass_person: %@ - %p",rootMetaclass_person, rootMetaclass_person);
     
     NSLog(@"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
     
     // The superclass object of the class object
     Class superclass_person = class_getSuperclass(class_person);
     // Superclass object of the metaclass object
     Class superMetaclass_person = class_getSuperclass(metaclass_person);
     // Superclass object of the rootMetaclass object
     Class superRootMetaclass_person = class_getSuperclass(rootMetaclass_person);
     
     NSLog(@"superclass_person : %@ - %p",superclass_person, superclass_person);
     NSLog(@"superMetaclass_person : %@ - %p",superMetaclass_person, superMetaclass_person);
     NSLog(@"superRootMetaclass_person: %@ - %p",superRootMetaclass_person, superRootMetaclass_person);
     
     //3. The isa flow and inheritance chain of the root class instance object.
     NSLog(@"");
     NSLog(@"Root class print");
     NSObject *object = [[NSObject alloc] init];
     / / class object
     Class class_object = object_getClass(object);
     / / object metaclass
     Class metaclass_object = object_getClass(class_object);
     / / rootMetaclass object
     Class rootMetaclass_object = object_getClass(metaclass_object);
     
     NSLog(@"class_object : %@ - %p",class_object, class_object);
     NSLog(@"metaclass_object : %@ - %p",metaclass_object, metaclass_object);
     NSLog(@"rootMetaclass_object: %@ - %p",rootMetaclass_object, rootMetaclass_object);
     
     NSLog(@"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
     
     // The superclass object of the class object
     Class superclass_object = class_getSuperclass(class_object);
     // Superclass object of the metaclass object
     Class superMetaclass_object = class_getSuperclass(metaclass_object);
     // Superclass object of the rootMetaclass object
     Class superRootMetaclass_object = class_getSuperclass(rootMetaclass_object);
     
     NSLog(@"superclass_object : %@ - %p",superclass_object, superclass_object);
     NSLog(@"superMetaclass_object : %@ - %p",superMetaclass_object, superMetaclass_object);
     NSLog(@"superRootMetaclass_object: %@ - %p",superRootMetaclass_object, superRootMetaclass_object);
Copy the code

3. LLDB print analysis

The red arrow represents the inheritance chain of the class object, the yellow arrow represents the inheritance chain of the metaclass object, and the green arrow represents the inheritance chain of the root metaclass object.

According to the figure:

  1. The parent of the subclass’s class object is the class object of the parent, the parent of the class object of the parent is the class object of the root class, and the class object of the root class is nil.
  2. The parent of the metaclass of the subclass is the metaclass of the parent, and the parent of the metaclass of the root class is the metaclass of the root class.

In combination with the classic picture below, it becomes clearer.

This isa widely circulated and classic picture, which describes the isa process and the inheritance chain of class. Looking at this picture through the above analysis, it suddenly becomes clear. I always couldn’t understand this picture before.

In fact, whether it isa subclass, parent class, root class isa process and class inheritance chain are basically the same, the real difference is the rootMetaclass object (rootMetaclass), isa process here, isa pointer refers to the rootMetaclass object itself, and the parent of the rootMetaclass object is the root class. And the parent of the root object is nil.