一、class返回对象lldb调试
首先看代码1
BOOL re1 = [[NSObject class] isKindOfClass:[NSObject class]];
[类名 class]返回的是什么东西,我们先查看
objc源码
+ (Class)class {
return self;
}
源码很简单,返回
self就是Class本身,通过lldb调试探究一下打印下
class1
(lldb) x/4gx class1
0x100379140: 0x00000001003790f0 0x0000000000000000
0x100379150: 0x00010001012bd3f0 0x0001801000000000
po一下isa
(lldb) po 0x00000001003790f0
NSObject
再对
isa进行x/4gx
(lldb) x/4gx 0x00000001003790f0
0x1003790f0: 0x00000001003790f0 0x0000000100379140
0x100379100: 0x0003000100717d30 0x0001e03400000000
都是
0x00000001003790f0,继续po
(lldb) po 0x00000001003790f0
NSObject
isa还是指向了自己,就是NSObject根类的元类——根元类,从下面这幅图可以看出
因为
NSObject是特殊情况,那可以继续探究,ApplePerson继承于NSObject
@interface ApplePerson : NSObject{
NSString *salary;
}
打印下内存
(lldb) x/4gx class2
0x100008498: 0x0000000100008470 0x0000000100379140
0x1000084a8: 0x000000010036d0e0 0x0000802800000000
po一下
po 0x0000000100008470
ApplePerson
ApplePerson没问题,再x/4gx一下
(lldb) x/4gx 0x0000000100008470
0x100008470: 0x00000001003790f0 0x00000001003790f0
0x100008480: 0x000000010036d0e0 0x0000e03400000000
再po一下
(lldb) po 0x00000001003790f0
NSObject
拿到了
NSObject
现在很清晰,
[类名 class]返回了类对象,探究和源码一致,接下来,
二、类方法 isKindOfClass
现在我们看
isKindOfClass,翻阅源码
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = self->ISA(); tcls; tcls = tcls->getSuperclass()) {
if (tcls == cls) return YES;
}
return NO;
}
- (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = [self class]; tcls; tcls = tcls->getSuperclass()) {
if (tcls == cls) return YES;
}
return NO;
}
有两个方法一个类方法,一个实例方法,先看类方法
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = self->ISA(); tcls; tcls = tcls->getSuperclass()) {
if (tcls == cls) return YES;
}
return NO;
}
在
For循环里面,Class tcls = self->ISA();很明显tcls是拿到类对象的元类,和传进来的类进行对比,如果不对,再取tcls的父类进行对比,第一次循环
tcls = NSObject类的元类即根元类,而cls是NSObject类,所以不相等;
这时第二轮For循环,再取NSObject根元类的父类跟NSObject类对比,由于NSObject根元类的父类就是NSObject类,所以相等,下面的图也可以看得出来
再看下代码2
BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
NSLog(@"re1 = %hhd",re1);
运行下
re1 = 1
再测试普通类代码
BOOL re2 = [[ApplePerson class] isKindOfClass:[ApplePerson class]];
NSLog(@"re2 = %hhd",re2);
[ApplePerson class]得到ApplePerson类和[ApplePerson class]->isa类比,即ApplePerson的元类比,肯定匹配不了,那继续循环 --> 和ApplePerson的元类的父类比,即和根元类NSObject类比 --> 匹配不上,那继续循环,和根元类NSObject的父类比NSObject类比 --> 匹配不上,NSObject再上去就是nil,循环结束,返回NO,运行下
re2 = 0
三、实例方法 isKindOfClass
代码3
BOOL re3 = [[NSObject alloc] isKindOfClass:[NSObject class]];
NSLog(@"re3 = %hhd",re3);
先看下源码
- (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = [self class]; tcls; tcls = tcls->getSuperclass()) {
if (tcls == cls) return YES;
}
return NO;
}
分析一下,
Class tcls = [[NSObject alloc] class]实例对象class方法获取到类对象,和[NSObject class]获取到类方法是一样的,跑下代码
re3 = 1
代码4
BOOL re4 = [[ApplePerson alloc] isKindOfClass:[ApplePerson class]];
NSLog(@"re4 = %hhd",re4);
同理,
ApplePerson的实例对象走class方法返回ApplePerson类,和[ApplePerson class]是一致的,跑下代码
re4 = 1
再看下for循环
for (Class tcls = [self class]; tcls; tcls = tcls->getSuperclass()) {
if (tcls == cls) return YES;
}
如果没找到的话,会拿
tcls的父类和cls比,如果tcls所属类是cls类的子类,那也是返回1,验证一波 (ApplePerson的父类是NSObject)
代码 5
BOOL re5 = [[ApplePerson alloc] isKindOfClass:[NSObject class]];
NSLog(@"re5 = %hhd",re5);
运行,打印
re5 = 1
四、类方法 isMemberOfClass
代码 6
BOOL re6 = [[NSObject class] isMemberOfClass:[NSObject class]];
NSLog(@"re6 = %hhd",re6);
查看源码
+ (BOOL)isMemberOfClass:(Class)cls {
return self->ISA() == cls;
}
拿到类的isa的类,那就是拿到类的元类,所以self->ISA()是元类,而cls是类,所以并不相等,运行一下
re6 = 0
再看代码7
BOOL re7 = [[ApplePerson class] isMemberOfClass:[ApplePerson class]];
NSLog(@"re7 = %hhd",re7);
拿ApplePerson元类和ApplePerson类比,肯定不一样,运行代码
re7 = 0
五、实例方法 isMemberOfClass
代码8
BOOL re8 = [[NSObject alloc] isMemberOfClass:[NSObject class]];
NSLog(@"re8 = %hhd",re8);
看源码
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
对象class方法得到类对象和cls相比较,[[NSObject alloc] class]的得到NSObject类对象和[NSObject class]是一样的,验证一波
re8 = 1
代码9
BOOL re9 = [[ApplePerson alloc] isMemberOfClass:[ApplePerson class]];
NSLog(@"re9 = %hhd",re9);
也是一样得到
ApplePerson的类对象和传入的是一样的
re9 = 1