Lmsgsendnilself

Uninhibited Soul, Free Craziness

isKindOf&isMemberOf

| Comments

在objc工程的NSObject.mm文件里面关于这两个方法的定义如下:可以看出加入对[NSObject class],返回的是类对象而非元类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
+ (BOOL)isMemberOfClass:(Class)cls {
    return object_getClass((id)self) == cls;
}

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

+ (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = object_getClass((id)self); 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;
}

+ (Class)class {
    return self;
}

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

在objc-class.mm文件里面object_getClass的定义如下:

1
2
3
4
5
Class object_getClass(id obj)
{
    if (obj) return obj->getIsa();
    else return Nil;
}

继续跟踪在objc-object.h的文件中,可以看出即返回的是isa所指向的对象的类型,也就是说如果是NSObject,则返回元类,如果是aObj 则返回类对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
inline Class 
objc_object::getIsa() 
{
#if SUPPORT_TAGGED_POINTERS
    if (isTaggedPointer()) {
        uintptr_t slot = ((uintptr_t)this >> TAG_SLOT_SHIFT) & TAG_SLOT_MASK;
        return objc_tag_classes[slot];
    }
#endif
    return ISA();
}

inline Class 
objc_object::ISA() 
{
    assert(!isTaggedPointer()); 
    return isa.cls;
}

所以 ,这便很好地解决了sunnyxx示例的一个问题

1
2
3
4
BOOL res1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
BOOL res2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
BOOL res3 = [(id)[Sark class] isKindOfClass:[Sark class]];
BOOL res4 = [(id)[Sark class] isMemberOfClass:[Sark class]];

第一个YES,其他三个NO

  1. [(id)[NSObject class] isKindOfClass:[NSObject class]];在for循环的第一次执行时,变成判断NSObject元类是否和NSObject类对象相等,迭代一轮for循环,NSObject元类的父类为NSObject类对象,此轮判断相等

  2. [(id)[NSObject class] isMemberOfClass:[NSObject class]];就是判断NSObject元类是否和NSObject类对象相等,所以NO

  3. [(id)[Sark class] isKindOfClass:[Sark class]]; 在for循环的第一次执行时,变成判断Sark元类是否和Sark类对象相等,迭代一轮for循环,变成判断Sark元类的父类是否和Sark类对象相等,直到倒数第二轮,判断NSObject元类是否和Sark类对象相等。。。至最后终归找不到相同的,所以NO

  4. [(id)[Sark class] isMemberOfClass:[Sark class]];就是判断Sark元类是否和Sark类对象相等,所以NO

Comments