美文网首页
-isMemberOfClass:和-isKindOfClass

-isMemberOfClass:和-isKindOfClass

作者: QYCD | 来源:发表于2021-04-08 16:04 被阅读0次
- (BOOL)isKindOfClass:(Class)aClass;
Returns a Boolean value that indicates whether the receiver is an instance of given class or an instance of any class that inherits from that class.
返回一个布尔值,该值指示接收方是给定类的实例还是从该类继承的任何类的实例。
- (BOOL)isMemberOfClass:(Class)aClass;
Returns a Boolean value that indicates whether the receiver is an instance of a given class.
返回一个布尔值,该值指示接收方是否为给定类的实例。

查看objc源码:

+ (Class)class {
    return self;
}

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

+ (Class)superclass {
    return self->getSuperclass();
}

- (Class)superclass {
    return [self class]->getSuperclass();
}

+ (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->getSuperclass()) {
        if (tcls == cls) return YES;
    }
    return NO;
}

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

可以看到isMemberOfClass:和isKindOfClass:既有实例方法也存在类方法。

尤其对于isKindOfClass:方法,通过源码可以看到,其内部实现存在遍历的情况

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

- (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = [self class]; tcls; tcls = tcls->getSuperclass()) {
        if (tcls == cls) return YES;
    }
    return NO;
}
isa指针走向.png

以NSString为例:


isa

面试题,如下打印什么?为什么?

BOOL res1 = [[NSObject class] isKindOfClass:[NSObject class]];
BOOL res2 = [[Person class] isKindOfClass:[Person class]];
BOOL res3 = [[NSObject class] isMemberOfClass:[NSObject class]];
BOOL res4 = [[Person class] isMemberOfClass:[Person class]];
    
NSLog(@"res1: %d=res2: %d=res3: %d=res4: %d", res1, res2, res3, res4);

分析这样的,个人感觉需要对上面的isa指针走向图做到心中有图,以及对isKindOfClass:和isMemberOfClass:方法的底层实现做到理解。

BOOL res1 = [[NSObject class] isKindOfClass:[NSObject class]];

很显然,这里第一个调用者是[NSObject class],即是一个类对象在调用isKindOfClass:而不是某个类的实例对象。

结合isKindOfClass的底层实现:
[NSObject class],即NSObject类对象,而调用isKindOfClass:
则:

(Class tcls = self->ISA()) NSObject类对象的isa指针指向的是NSObject根元类, NSObject根元类 != NSObject类,循环继续;

  1. tcls = tcls->getSuperclass(),NSObject根元类的父类是NSObject类,此时 tcls == cls,return YES;
BOOL res2 = [[Person class] isKindOfClass:[Person class]];
  1. [Person class]为Person类对象,Person类对象的isa指向Person的元类对象, Person元类 != Person类,循环继续
  2. Person元类的superclass是根元类,根元类 != Person类,循环继续;
  3. 根元类的superclass是NSObject类,NSObject类 != Person类,循环继续;
  4. NSObject类的superclass是nil,nil != Person类,循环结束
  5. return NO;
BOOL res3 = [[NSObject class] isMemberOfClass:[NSObject class]];

[NSObject class] NSObject类的isa指向的是根元类,根元类 != NSObject类, return NO

BOOL res4 = [[Person class] isMemberOfClass:[Person class]];

[Person class] Person类的isa指向的是Person的元类,Person元类 != Person类,return NO

理解isKindOfClass和isMemberOfClass的区别
iOS底层原理 06 : isa走位&类继承的经典面试题
深入理解iOS开发中的isa指针

相关文章

网友评论

      本文标题:-isMemberOfClass:和-isKindOfClass

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