isKindOfClass和isMemberOfClass是很常用的两个方法,在开发中很少有用错的地方,但是在碰到相关的面试题时,却总是分不清楚......
以往通过看源码的实现来学习两个方法的区别,虽然知道了具体实现,但是总是会忘记,碰到具体例子时,难免会带入源码中思考很久,今天忽然发现了一个诀窍来区分两个方法。
isKindOfClass:
returns YES if the receiver is an instance of the specified class or an instance of any class that inherits from the specified class.
方法调用者是传入的类或类的子类的实例对象则返回YES。
isMemberOfClass:
returns YES if the receiver is an instance of the specified class.
方法调用者必须是传入的类的实例对象才返回YES。
- 首先两个方法区别在于一个循环判断了类和类的子类,另一个只判断了传入的目标类。这方面通过类目就可以区分。
2. 最最最最最最重要的一点
上面两个方法最重要的概念在于
实例对象 这四个字,
因为两个方法都不用是来判断调用者和传入类是否相等(以往总是以为是判断是否相等的,搞清楚这一点就忽然豁然开朗了。),而是为了判断调用者是否是传入类的实例对象
从源码可以明显的看出,方法内部会先获取调用者的类型,如果是实例对象就会获取出类对象,如果本身调用者就是类对象,会获取出元类,然后在与传入的参数作对比
下面代码中:
- 自己永远不可能是自己的实例对象,所以调用两个方法都会返回
NO - 但是第一行代码返回了
YES,这是因为NSObject的特殊性,NSObject_metaClass的superclass指向NSObject_class,所以导致了在源码中,查找superclass的是否又重新找到了NSObject_class本身。