iOS开发深入探索

iOS 捋清楚 isKindOfClass 与 isMember

2020-11-05  本文已影响0人  水煮杰尼龟
   今天从源码来彻底了解这俩方法的区别。

相信很多人应该都遇到过类似的面试题,日常开发中也用这俩方法做过不少判断,比如后台返回的数据是不是数组,是不是null,是不是字典,某个实例是不是指定的控制器等等。

BOOL res1 = [[NSObject class] isKindOfClass:[NSObject class]];
        BOOL res2 = [[NSObject class] isMemberOfClass:[NSObject class]];
        BOOL res3 = [[Person class] isKindOfClass:[Person class]];
        BOOL res4 = [[Person class] isMemberOfClass:[Person class]];

        NSLog(@"%d %d %d %d", res1, res2, res3, res4);
        
        BOOL res5 = [[[NSObject new]class] isKindOfClass:[NSObject class]];
        BOOL res6 = [[[NSObject new]class] isMemberOfClass:[NSObject class]];
        BOOL res7 = [[[Person new]class] isKindOfClass:[Person class]];
        BOOL res8 = [[[Person new]class] isMemberOfClass:[Person class]];
        
        NSLog(@"%d %d %d %d", res5, res6, res7, res8);
        
        BOOL res9 = [[NSObject new] isKindOfClass:[NSObject class]];
        BOOL res10 = [[NSObject new] isMemberOfClass:[NSObject class]];
        BOOL res11 = [[Person new] isKindOfClass:[Person class]];
        BOOL res12 = [[Person new] isMemberOfClass:[Person class]];
        
        NSLog(@"%d %d %d %d", res9, res10, res11, res12);

这里面牵扯到的源码如下:

+ (Class)class {
    return self;
}

- (Class)class {
    return object_getClass(self);
}

+ (BOOL)isMemberOfClass:(Class)cls {
    return self->ISA() == cls;
}

- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}

+ (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = self->ISA(); tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

- (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

先捋一下这几个方法

  1. 类方法+ (Class)class 返回的是他自身,即类对象。
  2. 实例方法- (Class)class 返回的object_getClass(self),即实例对象的isa,对这部分有点了解的应该知道,实例对象的isa 指向的就是类对象。
  3. 类方法+ (BOOL)isMemberOfClass:(Class)cls,判断的是类对象的isa(即元类)是否等于cls
  4. 实例方法- (BOOL)isMemberOfClass:(Class)cls,判断的是实例对象调用class方法的返回值(即如上2,也就是类对象)是否与cls相等。
  5. 类方法+ (BOOL)isKindOfClass:(Class)cls,这里会先取类对象的isa (self->ISA()),类对象的isa指向的是元类,判断元类是否与cls相等,而且这里是一个for循环,不相等的话会往元类的父类(tcls = tcls->superclass)循环去查找对比。
  6. 实例方法- (BOOL)isKindOfClass:(Class)cls,这里是先取实例对象的isa ([self class]),也就是类对象,判断类对象与cls是否相等,不相等的话会往类对象的父类(tcls = tcls->superclass)循环去查找对比。
对实例对象,类对象,元类不了解的可以看我前面的文章
捋清楚了上面几个方法之后,再来看看开头的面试题,是不是豁然开朗了。

下面我们一个个来康康。

最终打印结果与理论是相符的。


result

end

上一篇 下一篇

猜你喜欢

热点阅读