美文网首页
isKindOfClass:和isMemberOfClass的用

isKindOfClass:和isMemberOfClass的用

作者: Gxdy | 来源:发表于2018-09-29 11:18 被阅读0次

    本文将从NSObject源码的角度来讲述isKindOfClassisKindOfClass使用.
    如需要查看更多更新源码资源请前往苹果官方源码下载

    在进入正文之前先附上一张isa与superclass指针的指向结构图

    isa与superclass.png
    1. - isKindOfClass:(实例方法)
    • NSObject源码实现如下
    - (BOOL)isKindOfClass:(Class)cls {
        // 循环遍历直到匹配到对应class或者tcls==nil
        // (从上图可以知道tcls->superclass最终会指向nil)
        for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
            if (tcls == cls) return YES;
        }
        return NO;
    }
    
    • 分析:从源码可以知道- isKindOfClass: 实例对象方法会先通过isa找到调用者(实例对象)的类对象进行判断。如果tcls == cls,就结束遍历返回YES。如果tcls != cls,就会沿着superclass指向的方向寻找父类的类对象,直到条件成立或者tcls=nil。

    • 结论:通过实例对象访问- isKindOfClass:方法,判断的是实例对象类对象或者父类的类对象是否等于cls(传入的参数)

    • 如:

    UIView *view = [[UIView alloc] init];
    [view isKindOfClass: [UIView class]];     // --> YSE
    [view isKindOfClass: [NSObject class]];   // --> YSE
    
    1. + isKindOfClass:(类对象方法)
    • NSObject源码实现如下
    + (BOOL)isKindOfClass:(Class)cls {
        for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
            if (tcls == cls) return YES;
        }
        return NO;
    }
    
    • 分析:

      • 首先,源码中tcls 初始 值是object_getClass((id)self),这是一个元类对象
      • 之后tcls = tcls->superclass,任然是一个元类对象,之后又成NSObject的类对象,最后是nil(从上图可知元类对象superclass --> SuperClass的元类对象 --> RootClass的元类对象 --> NSObject的类对象 --> nil)。
    • 结论:通过实例对象访问+ isKindOfClass:方法,判断的是类对象元类对象或者父类的元类对象或者NSObject的类对象是否等于cls(传入的参数)

    • 如:

    [UILabel isKindOfClass: [UILabel class]];     // --> NO,元类对象 != [UILabel class](类对象)
    [UILabel isKindOfClass: object_getClass([UILabel  class])];   // --> YSE
    [[UILabel  class] isKindOfClass: object_getClass([UILabel  class])];  // --> YSE
    [[UILabel  class] isKindOfClass: object_getClass([UIView  class])];  // --> YSE
    [[UILabel  class] isKindOfClass: object_getClass([NSObject  class])];  // --> YSE
    [[UILabel  class] isKindOfClass: [NSObject  class]];  // --> YSE
    
    1. - isMemberOfClass:(实例方法)
    • NSObject源码实现如下
    - (BOOL)isMemberOfClass:(Class)cls {
        return [self class] == cls;
    }
    
    • 源码可知:判断的是类对象是否等于cls
    • 如:
    [[UILabel new] isMemberOfClass:[UILabel class]]; // YES
     [[UILabel new] isMemberOfClass:[UIView class]]; // NO
    
    1. + isMemberOfClass:(类对象方法)
    • NSObject源码实现如下
    + (BOOL)isMemberOfClass:(Class)cls {
        return object_getClass((id)self) == cls;
    }
    
    • 源码可知:判断的是类对象元类对象是否等于cls
    • 如:
    [UILabel isMemberOfClass:[UIView class]];  // NO
    [UILabel isMemberOfClass:object_getClass([UILabel  class])];  // YES
    
    1. 总结
    1. 不管是isKindOfClass还是isMemberOfClass
    • 类对象调用时,都是与调用者的元类对象传入参数进行判断;
    • 实例对象调用时,不管是isKindOfClass还是isMemberOfClass,都是与调用者的类对象传入参数进行判断;
    1. isKindOfClass具有继承关系,会沿着superclass遍历;isMemberOfClass,则没有继承关系,只会判断一次

    3.注意点与用法:

    • 要注意类对象调用时,判断的是元类对象
    • 要注意[NSObject class]+ isKindOfClass中的特殊性
    • 要注意isKindOfClass是有继承关系
    • 判断某个对象是什么类(忽略继承)时,尽量用isMemberOfClass
    • 判断某个对象是继承自什么类(包含继承)时,用isKindOfClass

    相关文章

      网友评论

          本文标题:isKindOfClass:和isMemberOfClass的用

          本文链接:https://www.haomeiwen.com/subject/svmpoftx.html