iOS

iOS-isKindOfClass和isMemberOfClas

2019-08-16  本文已影响0人  厦门_小灰灰

isKindOfClass和isMemberOfClass解析

先出一道题(其中Person类继承NSObject类)

    BOOL rs1 = [[NSObject class] isKindOfClass:[NSObject class]];
    BOOL rs2 = [[NSObject class] isMemberOfClass:[NSObject class]];
    BOOL rs3 = [[Person class] isKindOfClass:[Person class]];
    BOOL rs4 = [[Person class] isMemberOfClass:[Person class]];

    NSLog(@"rs1 = %d,rs2 = %d,rs3 = %d,rs4 = %d",rs1,rs2,rs3,rs4);

有没有哪位同学的答案是

1,1,1,0  //嘻嘻,我一开始也是这样觉得的。

可惜了,不是哦,结果是:

1,0,0,0

为啥子嘞!!!!!!!

文档描述为:
isKindOfClass:
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.(确定一个对象是否是一个类的成员,或者是派生自该类的成员.)

isMemberOfClass:
Returns a Boolean value that indicates whether the receiver is an instance of a given class.(确定一个对象是否是当前类的成员.)

另外通过阅读Runtime的源码,看到了isKindOfClass和isMemberOfClass的源码实现:

+ (BOOL)isMemberOfClass:(Class)cls {
    return object_getClass((id)self) == cls;
}

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

+ (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;
}

包括类方法和实例方法,平常我们接触多的是实例方法。

Person *p = [[Person alloc] init];
[p isKindOfClass:[Person class]];
[p isMemberOfClass:[Person class]];

不过在上面的题目中,涉及到了类方法。关于对象,类,元类(MetaClass)之间的关系,我直接贴上经典图,这个大家请另外搜索相关内容。

对象,类,元类之间的关系图.png

我们一句一句来分析
先提取一下公共调用的方法(函数)

//下面代码涉及到的方法与函数
//类对象返回自身
+ (Class)class {
    return self;
}

//如果obj不是nil,就返回对象isa指针指向的对象
Class object_getClass(id obj)
{
    if (obj) return obj->getIsa();
    else return Nil;
}

1. [[NSObject class] isKindOfClass:[NSObject class]];

[[NSObject class] isKindOfClass:[NSObject class]];

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

其中,类对象发送class消息的时候,返回的是自身,也就是类对象本身。所以 执行 的是

+ (BOOL)isKindOfClass:(Class)cls;

因为NSObject是根类,所以它的isa指针指向的是NSObject的元类,另外NSObject元类的superclass是NSObject本身。

所以isKindOfClass:这个类方法中的循环会返回YES。
这里我简单写一下循环的每一步:

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

//以下是执行的步骤
1.Class tcls = object_getClass((id)self)  执行后,tcls是NSObject元类,所以返回NO;
2.tcls目前是NSObject元类,tcls不是nil所以循环会继续执行,
tcls = tcls->superclass,
上面说了NSObject元类的父类是NSObject本身;所以tcls目前是NSObject本身;
3.继续执行语句,发现tcls == cls,所以返回YES。循环结束。

所以值为 YES。

2. [[NSObject class] isMemberOfClass:[NSObject class]];

[[NSObject class] isMemberOfClass:[NSObject class]];

+ (BOOL)isMemberOfClass:(Class)cls {
    return object_getClass((id)self) == cls;
}

我们直接分析类方法isMemberOfClass:,其中object_getClass((id)self)返回的是NSObject元类,但是cls是NSObject本身,所以不相等。

所以值为 NO。

3. [[Person class] isKindOfClass:[Person class]];

这边直接分析:

  1. [Person class]的值为Person类本身;

2.调用isKindOfClass:类方法,执行循环的步骤:

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

执行步骤:
1. Class tcls = object_getClass((id)self)  tcls是Person元类;
2. 执行循环语句,不过,tcls != cls,因为tcls 是Person元类, cls是Person类;
3. tcls = tcls->superclass,tcls为 NSObject元类;
4. 再次执行循环语句,不过,tcls != cls,因为tcls是NSObject元类,cls是Person类;
5. tcls = tcls->superclass,tcls为NSObject类;
6. 再次执行循环语句,不过,tcls != cls,因为tcls是NSObject类,cls是Person类;
7.  tcls = tcls->superclass,tcls为nil,因为NSObject类的父类是nil;
8. 再次执行循环语句,return NO;结束循环

所以值为 NO。

4. [[Person class] isMemberOfClass:[Person class]];

[[Person class] isMemberOfClass:[Person class]];

+ (BOOL)isMemberOfClass:(Class)cls {
    return object_getClass((id)self) == cls;
}

直接分析,因为object_getClass((id)self) 获取到的是 Person元类,而cls是Person类。

所以值为 NO。

分析完毕,至于isKindOfClass和isMemberOfClass的实例方法较为简单,大家可自行尝试!

over!

上一篇下一篇

猜你喜欢

热点阅读