The relationship between iOS classes and metaclasses

The whole thing is like this, the students want to verify whether resolveClassMethod is executed (resolveClassMethod is when an object calls a non-existent class method, this method will be executed, if you don’t understand, you need to make up for it, you can read this article: Objective- C message forwarding ), and then sent the following code:

[NSObject performSelector:@selector(hehe)];

After reading it, I was confused. PerformSelector is an instance method and NSObject is a class. Doesn't it report errors when compiled? Later, the test found that there would be no error.

Then began our story today:
we all know that writing like this will make mistakes

@interface TestObject : NSObject
@end
@implementation TestObject
- (void)method1{
       [TestObject method2];//这样调用一定会编译错误
}
- (void)method2{}

However, writing this way will not report an error

@interface TestObject : NSObject
@end
@implementation TestObject
- (void)method{
   [NSObject performSelector:@selector(hehe)];
}

Even writing like this will not report
an error. Create a category of NSObject

@interface NSObject (hehe)
+(void)run;
@end
@implementation NSObject (hehe)
-(void)run{
    NSLog(@"run.....");
}
@end

Then call

[NSObject run];

Why is this?

Look at a diagram

Picture.png

 

(This picture comes from the network)
Assuming that class A inherits from class B, class B inherits from NSObject
A is the Subclass (class) on the way, B is the Superclass (class) in the figure, and NSObject is the Root class (class);
A *a = [A new];
In fact, A is the same as a, but also an object, A is called a class object, and a is called an instance object.
Each class object has an isa pointer

 Class isa  OBJC_ISA_AVAILABILITY;

The isa pointer points to the metaclass of the object of this class. Each class is the object of its metaclass. The metaclass is the description of the class object, just like the description of the ordinary instance object.

The essence of the class method declared in each class is to put the method on the metaclass method list, so when the class calls the class method, it can be imagined that the object of the metaclass is calling an instance method.

The parent class of A is B, the parent class of the metaclass of A is the parent class of the B metaclass, the parent of B is NSObject, the parent of NSObject is nil, and the parent of B metaclass is the metaclass of NSObject; pay special attention One point, the parent class of the metaclass of NSObject is NSObject, and the isa pointer of NSObject points to the metaclass of NSObject. Therefore, all methods in NSObject are also owned by the metaclass of NSObject. 1, so use NSObject to call any NSObject in Instance methods can be successful, 2. This also explains that the above declaration is +(void)run; class method, and the implementation is -(void)run{ NSLog(@"run.....") ;} Instance method, the call will not crash.

Class and metaclass are a closed loop. The instance points to the class, the class points to the metaclass, the metaclass points to the metaclass, and the metaclass points to itself. The parent class of the root metaclass is NSObject.

Metaclasses are classes of Class objects. Each class (Class) has its own unique metaclass (each class has its own unique list of methods). This means that all class objects are different.

All power methods in NSObject, any class can be called through class methods.

All meta-classes use the meta-class of the base class as their base class. The same is true for the meta-class of the top-level base class, except that it points to itself.

Guess you like

Origin blog.csdn.net/wangletiancsdn/article/details/104260373