08.isKindOfClass的底层实现

BOOL result1 = [[NSObject class] isKindOfClass:[NSObject class]];
BOOL result2 = [[NSObject class] isMemberOfClass:[NSObject class]];
BOOL result3 = [[RYModel class] isKindOfClass:[RYModel class]];
BOOL result4 = [[RYModel class] isMemberOfClass:[RYModel class]];

NSLog(@"Class\n %hhd \n %hhd \n %hhd \n %hhd", result1, result2, result3, result4);

BOOL result5 = [[NSObject alloc] isKindOfClass:[NSObject class]];
BOOL result6 = [[NSObject alloc] isMemberOfClass:[NSObject class]];
BOOL result7 = [[RYModel alloc] isKindOfClass:[RYModel class]];
BOOL result8 = [[RYModel alloc] isMemberOfClass:[RYModel class]];

NSLog(@"Instacne\n %hhd \n %hhd \n %hhd \n %hhd", result5, result6, result7, result8);

思考一下,会输出什么?

结果:

2021-06-27 08:29:10.567002+0800 IsKindOf[62355:691675] Class
 1 
 0 
 0 
 0
2021-06-27 08:29:10.567836+0800 IsKindOf[62355:691675] Instacne
 1 
 1 
 1 
 1

如果仅从字面上去理解代码,那么你的答案应该会是不一样的的。我们从源码层面来理解一下吧,源码不长,很容易理解。

一、isKindOfClass

1.1 流程图-Class

Class-isKindOfClass
  • [NSObject class] 即 RootClass

    • RootClass -(ISA)> RootMetaClass -(superClass)> RootClass

    • true

  • [RYModel class]

    • [RYModel class] -(ISA)> RYModelMetaClass -(superClass)> RootMetaClass -(superClass)> RootClass -(superClass)> nil

    • false

1.2 流程图-Instance

Instance-isKindeOfClass
  • NSObjectInstance

    • NSObjectInstance -(class)> RootClass

    • true

  • RYModelInstance

    • RYModelInstance -(class)> RYModelClass

    • true

二、isMemberOfClass

这里就很简单了,就不展开说了。

三、你以为这就完了?

如果你看到这里觉得没啥问题?那就有问题了。。。

我们运行下OC源码,两个断点。

IsKindofClass01

运行之后发现 +/- (Bool)isKindOfClass:(Class)cls 居然根本没有调用。

3.1 汇编

通过断点汇编,我们在调用 isKindOfClass 的地方发现了这样的指令 objc_opt_isKindOfClass

3.2 objc_opt_isKindOfClass

在这里下断点,我们发现的确进到了这里。并且 ClassInstance 的方法都走到了这里。

IsKindOfClass02

编译器对这里进行的优化,用更高效的 objc_opt_isKindOfClass 代替了原有的方法。

四、参考

slowpath & fastpath

Last updated

Was this helpful?