isa指针
#import
@interface MJPerson : NSObject
+ (void)personClassMethod;
- (void)personInstanceMethod;
@end
@implementation MJPerson
+ (void)personClassMethod
{
}
- (void)personInstanceMethod
{
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
MJPerson *person = [[MJPerson alloc] init];
[person personInstanceMethod];
[MJPerson personClassMethod];
}
return 0;
}
将Objective-c代码转换成 C\C++的代码
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpps
找到[person personInstanceMethod];
的 C++实现
((void (*)(id, SEL))(void *)objc_msgSend)((id)person, sel_registerName("personInstanceMethod"));
找到[MJPerson personClassMethod];
的 C++实现
((void (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("MJPerson"), sel_registerName("personClassMethod"));
可以看出对象方法 C++实现是对instance
对象发送一个方法消息,类方法 C++实现是对class
对象发送一个方法消息。
但是对象方法是存放在class
对象中,类方法是存放在meta-class
对象中。也就是说instance
对象找到class
对象中的对象方法,class
对象找到meta-class
对象中的类方法。
- 当调用对象方法时,通过
instance
对象的isa
指针找到class
对象,最后找到对象方法的实现进行调用- 当调用类方法时,通过
class
对象的isa
指针找到meta-class
对象,最后找到类方法的实现进行调用
superclass指针
#import
@interface MJPerson : NSObject
+ (void)personClassMethod;
- (void)personInstanceMethod;
@end
@implementation MJPerson
+ (void)personClassMethod
{
}
- (void)personInstanceMethod
{
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
@end
@interface MJStudent : MJPerson
+ (void)studentClassMethod;
- (void)studentInstanceMethod;
@end
@implementation MJStudent
+ (void)studentClassMethod
{
}
- (void)studentInstanceMethod
{
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
}
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder
{
return nil;
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
MJStudent *student = [[MJStudent alloc] init];
[student personInstanceMethod];
[MJStudent personClassMethod];
}
return 0;
}
找到[student personInstanceMethod];
的 C++实现
((void (*)(id, SEL))(void *)objc_msgSend)((id)student, sel_registerName("personInstanceMethod"));
找到[MJStudent personClassMethod];
的 C++实现
((void (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("MJStudent"), sel_registerName("personClassMethod"));
[student personInstanceMethod];
通过isa
指针只能找到MJStudent
的class
对象,但是personInstanceMethod
存储在MJPerson
的class
对象中。
[MJStudent personClassMethod];
通过isa
指针只能找到MJStudent
的meta-class
对象,但是personClassMethod
存储在MJPerson
的meta-class
对象中。
这就需要MJStudent
的class
对象找到MJPerson
的class
对象中的对象方法,MJStudent
的meta-class
对象找到存储在MJPerson
的meta-class
对象中的类方法。
当
MJStudent
的instance
对象要调用MJPerson
的对象方法时,会先通过isa
找到MJStudent
的class
对象,然后通过superclass
找到MJPerson
的class
对象,最后找到对象方法的实现进行调用。
当
MJStudent
的class
对象要调用MJPerson
的类方法时,会先通过isa
找到MJStudent
的meta-class
对象,然后通过superclass
找到MJPerson
的meta-class
对象,最后找到类方法的实现进行调用。
isa 、superclass总结
-
instance
对象的isa
指向class
对象 -
class
对象的isa
指向meta-class
对象 -
meta-class
对象的isa
指向基类的meta-class
对象 -
class
对象的superclass
指向父类的class
对象如果没有父类,superclass指针为nil
-
meta-class
对象的superclass
指向父类的meta-class
对象基类的
meta-class
对象的superclass
指向基类的class
对象 -
instance
对象调用方法的轨迹isa
找class
对象,方法不存在,就通过superclass
找父类
最后方法不存在报错unrecognized selector send to instance *****
-
class
对象调用类方法的轨迹isa
找meta-clas
对象,方法不存在,就通过superclass
找父类
最后方法不存在报错unrecognized selector send to class *****
代码验证基类的meta-class
对象的superclass
指向基类的class
对象
Nsobject
的分类
#import "NSObject+test.h"
@implementation NSObject (test)
+ (void)test
{
NSLog(@"+[NSObject test]----%p", self);
}
@end
main
文件的代码
#import
#import "NSObject+test.h"
@interface MJPerson : NSObject
+ (void)test;
@end
@implementation MJPerson
+ (void)test
{
NSLog(@"+[MJPerson test]----%p", self);
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"[MJPerson class]---%p", [MJPerson class]);
NSLog(@"[NSObject class]---%p", [NSObject class]);
[MJPerson test];
[NSObject test];
}
return 0;
}
打印结果
结果看出MJPerson
的class
对象调用+[MJPerson test]
方法,NSObject
的class
对象调用+[NSObject test]
方法。
注释掉MJPerson
类的+ (void)test;
方法
#import
#import "NSObject+test.h"
@interface MJPerson : NSObject
+ (void)test;
@end
@implementation MJPerson
//+ (void)test
//{
// NSLog(@"+[MJPerson test]----%p", self);
//}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"[MJPerson class]---%p", [MJPerson class]);
NSLog(@"[NSObject class]---%p", [NSObject class]);
[MJPerson test];
[NSObject test];
}
return 0;
}
打印结果
结果看出MJPerson
的class
对象调用+[NSObject test]
方法,NSObject
的class
对象调用+[NSObject test]
方法。
再注释掉NSObject
类的- (void)test
方法,添加- (void)test
方法
#import "NSObject+test.h"
@implementation NSObject (test)
//+ (void)test
//{
// NSLog(@"+[NSObject test]----%p", self);
//}
- (void)test
{
NSLog(@"-[NSObject test]----%p", self);
}
@end
打印结果
结果看出MJPerson
的class
对象调用-[NSObject test]
方法,NSObject
的class
对象调用-[NSObject test]
方法。但是- (void)test
方法是存放在NSObject
的class
对象中,也就证明了基类的meta-class
对象的superclass
指向基类的class
对象。