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

  1. isa
  2. superclass
  3. Attribute property
  4. The instance method
  5. Agreement protocal
  6. 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
  7. 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

  1. isa
  2. superclass
  3. Class method information
  4. 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