-
今天通过
isa走向图
解决2到经典的面试题(这两道面试题可以说明你是否研究过底层,是否了解isa走位,而且还TM有坑!) -
我们先把超级经典的
isa走向图
啪出来:
1. 面试题1
要是这么长的面试题估计大家会犯慌!慢慢分析就好!反正没有时间规定!
还有:不知道如何看源码环境请看另一篇博客:objc4-787.1编译调试
- 上代码:
@interface XGPerson : NSObject
- (void)sayHello;
+ (void)sayHappy;
@end
@implementation XGPerson
- (void)sayHello{
NSLog(@"XGPerson say : Hello!!!");
}
+ (void)sayHappy{
NSLog(@"XGPerson say : Happy!!!");
}
@end
void xgClassMethod_classToMetaclass(Class pClass){
const char *className = class_getName(pClass);
Class metaClass = objc_getMetaClass(className);
Method method1 = class_getClassMethod(pClass, @selector(sayHello));
Method method2 = class_getClassMethod(metaClass, @selector(sayHello));
Method method3 = class_getClassMethod(pClass, @selector(sayHappy));
Method method4 = class_getClassMethod(metaClass, @selector(sayHappy));
//
NSLog(@"%s-%p-%p-%p-%p",__func__,method1,method2,method3,method4);
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
XGPerson *person = [XGPerson alloc];
Class pClass = object_getClass(person);
xgClassMethod_classToMetaclass(pClass);
}
return 0;
}
问:0代表无结果,1代表有结果,输出的是什么?
- 解释:
- 我们开始分析习题!
- 1、 主要方法是:
xgClassMethod_classToMetaclass
- 2、 最终结果就是查看
method
是否存在-
- 我们开始探究
xgClassMethod_classToMetaclass
- 我们开始探究
-
- 首先前两行代码就是获取元类
metaClass
- 首先前两行代码就是获取元类
-
- 我们可以先看下
class_getClassMethod
的源码:
- 我们可以先看下
Method class_getClassMethod(Class cls, SEL sel)
-
{ if (!cls || !sel) return nil;
return class_getInstanceMethod(cls->getMeta(), sel);
} //这个本质就是查看他的元类是否有实例方法!
* 4. 然后我们可以观察下`cls`如何`getMeta()`
```Objc
Class getMeta() {
if (isMetaClass()) return (Class)this;
else return this->ISA();
}
-
- 我们所需要的信息都已经准备好了。那么我们可以找答案了!!
-
- 答案解析!
method1
是查看pClass
是否有sayHello
,sayHello
是实例方法,存在类中!然后通过源码知道:class_getInstanceMethod(cls->getMeta(), sel);
他去他的元类中找sayHello
所以找不到!所以是0
method2
是查看metaClass
是否有sayHello
,sayHello
是实例方法,去元类的元类中(getMeta
,是元类
的话返回自己了)找sayHello
所以找不到!所以是0
method3
中查看:首先sayHappy
是类方法!method3
的意思就是在pClass
的元类中是否有实例方法sayHappy
,所以是1
method4
就有点意思了!,sayHappy
是类方法!,这个要在元类的元类
里面找!,就要看isa的走向图
了!,而且getMeta
的实现:如果是元类就返回自己!总体来说的意思是:就是从元类
中找实例方法
:sayHappy
,所以答案是1
-
- 查看输出:
-
- 答案:
xgClassMethod_classToMetaclass-0-0-1-1
- 答案:
类中存储实例方法,元类中存储类方法(以实例方法的形式)
2. 面试题2
- 出题上代码:(问:输出的是啥)
BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
BOOL re3 = [(id)[XGPerson class] isKindOfClass:[XGPerson class]];
BOOL re4 = [(id)[XGPerson class] isMemberOfClass:[XGPerson 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)[XGPerson alloc] isKindOfClass:[XGPerson class]];
BOOL re8 = [(id)[XGPerson alloc] isMemberOfClass:[XGPerson class]];
NSLog(@" re5 :%hhd\n re6 :%hhd\n re7 :%hhd\n re8 :%hhd\n",re5,re6,re7,re8);
- 来来来,老规矩,咱们吧需要的源码全都粘出来!
// isKindOfClass 在编译是llvm处理过:objc_opt_isKindOfClass
// Calls [obj 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->superclass) {
if (tcls == otherClass) return YES;
}
return NO;
}
#endif
return ((BOOL(*)(id, SEL, Class))objc_msgSend)(obj, @selector(isKindOfClass:), otherClass);
}
//类方法
+ (BOOL)isMemberOfClass:(Class)cls {
return self->ISA() == cls;
}
//实例方法
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
- 好了!又来分析了!看我答案之前大家最好想一波!
-
-
根据源码调试:类方法和实例方法isKindOfClass都会进入:objc_opt_isKindOfClass.
-
1.1. 当是类方法的时候,
class1
isKindOfClass:
class2
:obj
为class1
,obj
的isa
指向的类的父类,相等于class2
, 返回YES。 -
1.2. 是实例方法时:
object1
isKindOfClass
class
:obj
为object1
,根据isa流程图可知:obj的isa指向创建他的类,所以意思是:object1
是否是class
的本类
或子类
创建的对象.
-
所以类方法可以得知
re1
和re3
的值:
re1
:NSObject--(isa)-->NSObject(元类)——(继承)——>NSObject
NSObject
==NSObject
! 所以是1
re3
:XGPerson--(isa)-->XGPerson(元类)--(继承)-->NSObject
XGPerson
==NSObject
! 所以是0。
所以实例方法可以得知
re5
和re7
re5
:[NSObject alloc]
是NSObject
创建的对象
re7
:[XGPerson alloc]
是XGPerson
创建的对象
所以都是1
扩展:BOOL re7 = [(id)[XGPerson alloc] isKindOfClass:[NSObject class]];这样的话,re7也为1
-
- 分析类方法:
A
isMemberOfClass
B
:就是A
的isa
是否与B
相同
- 分析类方法:
** 类和元类的名称可能叫法相同,但是不是一个东东啊!! **
所以可以得知
re2
和re4
的值:
re2
:NSObject--(isa)-->NSObject(元类)
re4
:XGPerson--(isa)-->XGPerson(元类)
所以都是0
-
- 实例方法
object2
isMemberOfClass
class2
:[object2 class]
是否与class2
相同
- 实例方法
所以可以得知
re6
和re8
re6
:[NSObject alloc].class
==NSObject
re8
:[XGPerson alloc].class
==XGPerson
所以都是1
兄弟们!!这两道面试题解释的有点长!!,希望对大家有帮助~~,我也是这么一步步解释才明白的!