This article has been synchronized to the brief: ios-ISA, the superclass pointer, and the metaclass superclass pointing to the base class itself
Object of a.
Instance objects, also called instance objects
Class objects, also known as class objects
Meta-calss objects, also known as metaclass objects
This paper will explore the following issues:
- What information is contained in these objects
- How is this information related
- Where do member variables exist
- Where do class methods and instance methods exist
- How do I find superclasses
The instance objects
1. What is instance object
Everything after +alloc is instance. It is also important to note that instance objects are not just NSObject objects. There is also a proxy class, NSProxy, that can also create instance objects
// Create an object NSObject* obj = [NSObject alloc];Copy the code
Class object
1. Obtain the class object
Create a ClassObject class inherited from NSObject
- (void)viewDidLoad { [super viewDidLoad]; ClassObject *clsObj = [[ClassObject alloc] init]; [self fetchClassWithClassObject:clsObj]; } / / get all the methods of class - (void) fetchClassWithClassObject: (ClassObject *) clsObj {class objClass1 = [clsObj class]; Class objClass2 = [ClassObject class]; Class objClass3 = object_getClass(clsObj); NSLog(@"\n objClass1 = %@ \n objClass2 = %@ \n objClass3 = %@ \n",NSStringFromClass(objClass1), NSStringFromClass(objClass2), NSStringFromClass(objClass3) ); NSLog(@"\n\n objClass1 = %p \n objClass2 = %p \n objClass3 = %p", objClass1, objClass2, objClass3); 2021-05-04 10:34:36.333929+0800 ClassDemo[26079:8911440] objClass1 = ClassObject objClass2 = ClassObject ObjClass1 = 0x109a61548 objClass2 = Class3 = ClassObject 2021-05-04 10:34:36.334052+0800 ClassDemo[26079:8911440] objClass1 = 0x109a61548 objClass2 = 0x109a61548 objClass3 = 0x109a61548Copy the code
In the project, there is only one object per class. But what is the difference between the above three methods of obtaining a class? The first two methods get the value of the current instance Class directly, but the third method is different. This method gets the value of the current instance isa
As an experiment, add a KVO to clsObj
[clsObj addObserver:self forKeyPath:@"class" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
Copy the code
The printed result becomes
2021-05-04 10:54:32.415419+0800 ClassDemo[28990:8934226]
objClass1 = ClassObject
objClass2 = ClassObject
objClass3 = NSKVONotifying_ClassObject
2021-05-04 10:54:32.415562+0800 ClassDemo[28990:8934226]
objClass1 = 0x10fea3550
objClass2 = 0x10fea3550
objClass3 = 0x600001300240
Copy the code
The third value becomes NSKVONotifying_ClassObject
####2. Information in the class object
- isa
- superclass
- Attribute property
- The instance method
- Agreement protocal
- Member variables, the member variable information here is not the value of the member variable in an instance, but what member variables are in the Class, NSSting, int
- other
Meta – class object
You can use the object_getClass function to obtain the isa class of the meta-class object
- (void)fetchMetaClassWithClassObject:(ClassObject *)clsObj { //1. Get an object's ISA Class objIsa = object_getClass(clsObj); // Get the metaClass object Class metaClass = object_getClass(objIsa); NSLog(@" \n metaClass = %p \n metaClass = %@", metaClass, NSStringFromClass(metaClass)); }Copy the code
You’ll find that the metaclass is the same as the current Class, but it’s the address of another object. Second, whether a Class object or a metaclass object is of type Class, it’s the same memory structure, but it contains different information and uses different things
Information in a meta-class object
- isa
- superclass
- Class method information
- other
Object to summarize
- There are three types of objects: instance, class, and meta-class
- The values of member variables are stored in instance
- Attributes, instance methods, and protocol are stored in class
- Class methods are stored in meta-class
2. Isa
How are these three objects related? Is associated through ISA:
The value of isa for instance objects is class objects, and the value of ISA for class objects is meta-calss objects
Since instance methods exist in class objects, how do you find the implementation when sending a message to an instance object?
When an instance method is called, the class is found through the ISA in the instance object to find the implementation of the corresponding instance method
The same is true for class method calls:
When a class method is called, the meta-class is found through the ISA pointer to the class object and the corresponding class method implementation is found
Three superclass.
The superclass pointer defines two classes relative to a class object and a meta-class object: Person inherits from NSObject and Student inherits from Person. Here is a scenario where instance methods implemented in Person are called from Student’s instance object as follows:
Student class = Person class = Person class = Person class = Person class = Person class
The same is true for class method calls
Isa and Superclass
In the NSObject header file, you can see an ISA member variable of type Class
@interface NSObject <NSObject> { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-interface-ivars" Class isa OBJC_ISA_AVAILABILITY; #pragma clang diagnostic pop }Copy the code
In the NSObject protocol there is a member variable of type Class superclass
@protocol NSObject ··· @Property (readonly) Class superclass; ... @ the endCopy the code
In objective-C object-oriented language design, function call, member variable storage and access are implemented
In this figure, you can see three classes: Rootclass, Superclass, and SubClass, which are the base class, Superclass, and SubClass, respectively. From left to right, there are instance objects, class objects, and metaclasses, respectively. For example: We create a Person class that inherits from NSObject, and a Student class that inherits from Person. So NSObject, Peron, Student correspond to Rootclass, Superclass, SubClass, and the Instance on the left represents the Instance that we alloc out
As can be seen from the figure:
isa
- The ISA of the instance points to the class object, and the ISA of the class object points to the metaclass object
- The ISA of a meta-class all point to the meta-class of the base class
superclass
- The superclass of class points to the parent, or nil if there is no parent
- The superclass of a meta refers to the superclass of the parent class, and the superclass of the base class refers to the class of the base class
Call the trajectory
- Instance object: isa finds the class, and if the method does not exist, finds the superclass
- Class object: ISA finds meta-classes, and if the method doesn’t exist, superclass is used to find the superclass
5. Verifying the relationship between ISA, class and superclass
It says something
The isa value of an instance object isa class object, and the isa value of class isa meta-class object
The figure above is also reflected, and then mark the number as follows:The next step is to prove that these five lines are correct by creating the Person class that inherits from NSObject as follows:
Person *instanceObj = [[Person alloc] init]; // first line (instance isa value isa Class object) Class classCls = object_getClass(instanceObj); Class metaCls = object_getClass(classCls); Class rootMetaCls0 = class_getSuperclass(metaCls); Class rootMetaCls1 = object_getClass(metaCls); //RootClass meta-class class rootMetaCls = object_getClass(rootMetaCls0); NSLog(@"\n instanceObj = %p \n classCls = %p \n metaCls = %p \n rootMetaCls0 = %p \n rootMetaCls1 = %p \n rootMetaCls = %p\n", instanceObj, classCls, metaCls, rootMetaCls0, rootMetaCls1, rootMetaCls);Copy the code
Print result:
2021-05-04 16:25:08.423125+0800 ClassDemo[32740:9240333]
instanceObj = 0x600002d7c0e0
classCls = 0x109a21800
metaCls = 0x109a217d8
rootMetaCls0 = 0x7fff86d48638
rootMetaCls1 = 0x7fff86d48638
rootMetaCls = 0x7fff86d48638
Copy the code
Look back three values is the same, should be clear by now, but the above code, no isa related, we just get the corresponding object type (Class), now want to see the corresponding isa value is how much, because the isa has protection, we can get, by way of KVC can also refer to write a Class structure. Use the Bridge to Bridge C/C++ to access the ISA object address, provided that you know what the object structure looks like from the clang compiler. Let’s take the KVC approach and modify the code slightly to check the ISA value:
NSObject *object = [[NSObject alloc] init]; Class rootCls = object_getClass(object); Person *instanceObj = [[Person alloc] init]; // first line (instance isa value isa Class object) Class classCls = object_getClass(instanceObj); Class metaCls = object_getClass(classCls); Class rootMetaCls0 = class_getSuperclass(metaCls); Class rootMetaCls1 = object_getClass(metaCls); //RootClass meta-class class rootMetaCls = object_getClass(rootMetaCls0); //root-meta-class superclass rootMetaSuperCls = class_getSuperclass(rootMetaCls0); NSLog(@"\n rootCls = %p \n instanceObj = %p \n classCls = %p \n metaCls = %p \n rootMetaCls0 = %p \n rootMetaCls1 = %p \n rootMetaCls = %p \n rootMetaSuperCls = %p \n", rootCls, instanceObj, classCls, metaCls, rootMetaCls0, rootMetaCls1, rootMetaCls, rootMetaSuperCls); NSLog(@" instanceobj-isa = %p \n classcls-ISA = %p \n metacls-ISA = %p \n rootMetacls0-ISA = %p \n", [instanceObj valueForKey:@"isa"], [classCls valueForKey:@"isa"], [metaCls valueForKey:@"isa"], [rootMetaCls0 valueForKey:@"isa"]);Copy the code
The printed result is:
2021-05-04 16:55:11.688427+0800 ClassDemo[49442:9299385]
rootCls = 0x7fff86d48660
instanceObj = 0x600003e38170
classCls = 0x10e5b4810
metaCls = 0x10e5b47e8
rootMetaCls0 = 0x7fff86d48638
rootMetaCls1 = 0x7fff86d48638
rootMetaCls = 0x7fff86d48638
rootMetaSuperCls = 0x7fff86d48660
2021-05-04 16:55:11.688742+0800 ClassDemo[49442:9299385]
instanceObj-isa = 0x10e5b4810
classCls-isa = 0x10e5b47e8
metaCls-isa = 0x7fff86d48638
rootMetaCls0-isa = 0x7fff86d48638
Copy the code
It’s clear from the print:
- Instance object’s ISA points to the Class object (0x10657A808, first line)
- The ISA of the Class object points to the meta-class object (0x10657A7e0, second line)
- The Superclass of meta-class is root-meta-class (0x7ffF86D48638, third line)
- Meta-class isa points to root-meta-class (0x7ffF86d48638, fourth line)
- Root-meta-class isa points to itself (0x7ffF86D48638, line 5)
- The Superclass of root-meta-class is Rootclass (0x7FFF86D48660)
6. Develop
Since the Superclass of the primitive class refers to the base class, we find a magic problem: if a class method is never found and the object method of the base class is found, the object method of the base class is called, that is, a + method of the subclass, and a – method of the base class is called. This is because the iOS messaging method mechanism does not distinguish object methods from class methods. The code validates this by defining an NSObject class that adds an object method to NSObject
.h
@interface NSObject (category)
- (void)showName;
@end
.m
@implementation NSObject (category)
- (void)showName {
NSLog(@"NSObject (category) class = %@", NSStringFromClass([self class]));
}
@end
Copy the code
Person inherits from NSObject and declares that the + (void)showName method is not implemented at.h.
.h
@interface Person : NSObject
+ (void)showName;
@end
.m
@implementation Person
@end
Copy the code
call
[Person showName];
Copy the code
We actually execute the – (void)showName method defined in the NSObject category when we call Person’s + (void)showName method
2021-05-04 17:09:56.436515+0800 ClassDemo[51930:9318834] NSObject (category) class = Person
Copy the code
This is also good proof that the Superclass of a primitive object points to the base class