程序员社区

OC-Runtime-isMemberOfClass,isKindOfClass区别

OC-Runtime-isMemberOfClass,isKindOfClass区别插图

isMemberOfClass 和 isKindOfClass 区别

先从面试题的打印语句开始:

***********************?MJPerson.h ?**************************
#import <Foundation/Foundation.h>

@interface MJPerson : NSObject

@end
***********************?MJPerson.m ?**************************  
#import "MJPerson.h"

@implementation MJPerson

@end

四句输出语句,仔细想想会打印输出什么:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"%d", [NSObject isKindOfClass:[NSObject class]]); // 1
        NSLog(@"%d", [NSObject isMemberOfClass:[NSObject class]]); // 0
        NSLog(@"%d", [MJPerson isKindOfClass:[MJPerson class]]); // 0
        NSLog(@"%d", [MJPerson isMemberOfClass:[MJPerson class]]); // 0
    }
}

RUN>

*********************** ?运行结果? **************************
2021-05-08 15:33:35.732674+0800 Interview01-class[3834:142154] 1
2021-05-08 15:33:35.733220+0800 Interview01-class[3834:142154] 0
2021-05-08 15:33:35.733273+0800 Interview01-class[3834:142154] 0
2021-05-08 15:33:35.733296+0800 Interview01-class[3834:142154] 0

找到源码

OC-Runtime-isMemberOfClass,isKindOfClass区别插图1

+ (BOOL)isMemberOfClass:(Class)cls {

// 获取接收者的元类对象 , 直接和 传进来的 cls 比较,也就是说传进来的 cls 也应该是 元类对象,否则就为 false
    return object_getClass((id)self) == cls;
}

- (BOOL)isMemberOfClass:(Class)cls {
// 获取消息接收者的类对象 和 传入的 cls 判断是否相等
    return [self class] == cls;
}

+ (BOOL)isKindOfClass:(Class)cls {

// 第一步: 获取传入的消息接收者的元类对象
// 第二步: 判断和传入的 cls 是否相等,也就是说传入的也必须是 元类对象, 否则为 false
// 第三步: 如果不相等,继续找这个 元类对象的 superclass 继续比较,直到 superclass 为 nil.
    for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

- (BOOL)isKindOfClass:(Class)cls {
// 第一步: 取出消息接收者的类对象,和传入的 cls 判断是否相等
// 第二步: 如果不相等,继续找这个类对象的 superclass 继续比较,直到 superclass 为nil 为止.
    for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

根据源码分析,+开头的方法,==传入的必须是元类对象==,所以我们后面三条输出语句都是false.

[NSObject isKindOfClass:[NSObject class]]也是使用的+类方法,比较的元类对象,为什么输出的true 在OC对象的本质-isa指针 superclass指针详解

OC-Runtime-isMemberOfClass,isKindOfClass区别插图2

因为基类元类对象的 superclass 指向类对象 所以最后回到了NSObject 类对象,事实上,所有继承自NSObject类的子类调用[isKindOfClass:[NSObject class]]都是成立的.

特别备注

本系列文章总结自MJ老师在腾讯课堂iOS底层原理班(下)/OC对象/关联对象/多线程/内存管理/性能优化,相关图片素材均取自课程中的课件。如有侵权,请联系我删除,谢谢!

赞(0) 打赏
未经允许不得转载:IDEA激活码 » OC-Runtime-isMemberOfClass,isKindOfClass区别

一个分享Java & Python知识的社区