判断对象类型
-(BOOL) isKindOfClass: classObj判断是否是这个类或者这个类的子类的实例
-(BOOL) isMemberOfClass: classObj 判断是否是这个类的实例
接下来我们来看一道经典面试题:
BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]]; //
BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]]; //
BOOL re3 = [(id)[LGPerson class] isKindOfClass:[LGPerson class]]; //
BOOL re4 = [(id)[LGPerson class] isMemberOfClass:[LGPerson class]]; //
NSLog(@" re1 :%hhd\n re2 :%hhd\n re3 :%hhd\n re4 :%hhd\n",re1,re2,re3,re4);
BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]]; //
BOOL re6 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]]; //
BOOL re7 = [(id)[LGPerson alloc] isKindOfClass:[LGPerson class]]; //
BOOL re8 = [(id)[LGPerson alloc] isMemberOfClass:[LGPerson class]]; //
NSLog(@" re5 :%hhd\n re6 :%hhd\n re7 :%hhd\n re8 :%hhd\n",re5,re6,re7,re8);
输出结果
re1 :1
re2 :0
re3 :0
re4 :0
re5 :1
re6 :1
re7 :1
re8 :1
看到这个结果会不会很诧异,说实话我是很诧异ret3的结果
既然感到奇怪我们就来深入研究一下isKindOfClass和isMemberOfClass
首先通过调试我们定位到isKindOfClass的底层调用源码
BOOL
objc_opt_isKindOfClass(id obj, Class otherClass)
{
#if __OBJC2__
if (slowpath(!obj)) return NO;
Class cls = obj->getIsa();
if (fastpath(!cls->hasCustomCore())) {
for (Class tcls = cls; tcls; tcls = tcls->getSuperclass()) {
if (tcls == otherClass) return YES;
}
return NO;
}
#endif
return ((BOOL(*)(id, SEL, Class))objc_msgSend)(obj, @selector(isKindOfClass:), otherClass);
}
+ (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;
}
这边有个宏__OBJC2__,当版本比较老,会通过objc_megSend调用isKindOfClass方法
注意到源码Class cls = obj->getIsa();这边拿的是obj的isa指向的类,我们知道对象的isa指向的是类,类的isa指向的是元类
[(id)[NSObject class] isKindOfClass:[NSObject class]];
这个拿的是NSObject根类的isa也就是根元类,和NSObject类对比,显然不是,后面通过循环,获取根元类的父类,根元类的父类是NSObject根类和NSObject类对比两个相同,所以返回true
[(id)[LGPerson class] isKindOfClass:[LGPerson class]];
同理,LGPerson的元类跟LGPerson类对比不同,而LGPerson元类的父类跟LGPerson也不一样,所以返回false
[(id)[NSObject alloc] isKindOfClass:[NSObject class]];
这边拿的是NSObject对象的isa,也就是NSObject类,所以是一样的
[(id)[LGPerson alloc] isKindOfClass:[LGPerson class]];
这边拿的是LGPerson对象的isa,也就是LGPerson类,所以是一样的
我们再来看看isMemberOfClass的源码
1
+ (BOOL)isMemberOfClass:(Class)cls {
return self->ISA() == cls;
}
2
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
这个直接拿isa指针来跟cls对比,接下来我们来分析一下
BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
[NSObject class]的isa是根元类,[NSObject class]根类,两个肯定不一样结果为false
[(id)[LGPerson class] isMemberOfClass:[LGPerson class]]
[LGPerson class]的isa是LGPerson元类,[LGPerson class]是LGPerson类,结果为false
[(id)[NSObject alloc] isMemberOfClass:[NSObject class]]
首先这边调用的是实例方法也就是上面的2这个代码 ,源码里面直接[self class] == cls,我们来分析一下[[NSObject alloc] class]=NSObject 类所以返回true
[(id)[LGPerson alloc] isMemberOfClass:[LGPerson class]]
同理,[[LGPerson alloc] class] = LGPerson类 所以也是返回true
网友评论