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 is
person
Memory distribution, and0x000021a1000080e9(isa) & 0x0000000ffffffff8ULL
,person
theisa
The memory address pointed to is0x00000001000080e8
And calledSHPerson
Class object. - The second print is the memory distribution of the class object, and
0x00000001000080c0(isa) & 0x0000000ffffffff8ULL
, the obtained memory address is0x00000001000080c0
, Po prints the result namedSHPerson
The calSS object of. - Compare the first and second prints, the two are respectively
0x00000001000080e8
and0x00000001000080c0
The name of the printed class object is the same. - The third time is printing
0x00000001000080c0
Memory distribution, and0x00000001003790f0(isa) & 0x0000000ffffffff8ULL
, the obtained memory address is0x00000001003790f0
, Po prints the result namedNSObject
The calSS object of. - Comparing the previous two prints, I found that they were different.
0x00000001003790f0
and0x00000001000080e8
,0x00000001000080c0
The printed class object names are different. - The fourth time is printing
0x00000001003790f0
The memory distribution of this discoveryisa
That it should be the same as it is0x00000001003790f0
theisa
It’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:
- 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.
- 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.