OC追根溯源之Class

作者: Ro_bber | 来源:发表于2017-11-12 17:11 被阅读46次

前两天碰到一面试题:

//分辨下面res的是非
BOOL res1 = [[NSObject class] isKindOfClass:[NSObject class]];
BOOL res2 = [[NSObject class] isMemberOfClass:[NSObject class]];
BOOL res3 = [[Sark class] isKindOfClass:[Sark class]];
BOOL res4 = [[Sark class] isMemberOfClass:[Sark class]];

在这之前,我们先了解一下相关的定义:

Class

objc.hClass是这么定义的:

/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;

objc_class又是啥呢?在runtime.h中能看见:

struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class super_class                                        OBJC2_UNAVAILABLE;
    const char *name                                         OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;

MetaClass

上面能看到Class中有个isa参数,它是指向Class元类(MetaClass)的指针。

注意到isa也是一个Class的结构体,也就是说MetaClass其本质也是一个Class

我们可以把Meta Class理解为 一个Class对象的Class。简单的说:

  • 当我们发送一个消息给一个NSObject对象时,这条消息会在对象的类的方法列表里查找
  • 当我们发送一个消息给一个类时,这条消息会在类的Meta Class的方法列表里查找

之后就有了下面的这张图:

ocClass.jpg

能看到:

  • 每个Class都有一个isa指针指向一个唯一的MetaClass
  • 每一个MetaClassisa指针都指向最上层的MetaClass(图中的NSObjectMetaClass
  • 最上层的MetaClassisa指针指向自己,形成一个回路
  • 每一个MetaClasssuper class指针指向它原本ClassSuper ClassMetaClass
  • 最上层的MetaClassSuper Class指向NSObject Class本身
  • 最上层的NSObject Classsuper class指向 nil

接下来我们看看objc源码中(源码可到这里下载),在文件Object.mm内,上面相关方法的定义:

+ (Class)class {  
    return self;  
}
- (BOOL)isKindOf:aClass
{
    Class cls;
    for (cls = isa; cls; cls = cls->superclass)
        if (cls == (Class)aClass)
            return YES;
    return NO;
}
- (BOOL)isMemberOf:aClass
{
    return isa == (Class)aClass;
}

那么,BOOL res1 = [[NSObject class] isKindOfClass:[NSObject class]];就可以这样对应起来理解了:

[NSObject class]拿到的是self,类方法的return self,即上图紫色的NSObject(Class)

根据上面- (BOOL)isKindOf:aClass的实现,for循环首先拿到的cls = isa,也就是clsNSObject(Class)MetaClass。显然这时候cls == (Class)aClass不成立。

随后,cls = cls->superclass,即cls变成了NSObject(Class)MetaClasssuperclass,根据图示可以,superclass指向的是NSObject(Class),至此cls == (Class)aClass成立,返回YES

同样的道理,分析BOOL res3 = [[Sark class] isKindOfClass:[Sark class]];:

[Sark class]拿到的是Sark(Class),而- (BOOL)isKindOf:aClasscls拿到的值依次是Sark Meta Class->NSObject Meta Class->NSObject Class -> nil,没有相等的,return NO

剩下两个,根据- (BOOL)isMemberOf:aClass的实现,很容易得出结论会return NO

喜欢我的可以关注收藏我的个人博客:Ro.bber

相关文章

  • OC追根溯源之Class

    前两天碰到一面试题: 在这之前,我们先了解一下相关的定义: Class 在objc.h中Class是这么定义的: ...

  • OC-Runtime-Class结构和OC消息机制

    OC - Runtime - Class 结构 和 OC 消息机制 Runtime 源码中 Class 结构如下:...

  • OC之class与meta-class

    核心规则:类的实例对象的 isa 指向该类;该类的 isa 指向该类的 metaclass。 通俗说法:成员方法记...

  • iOS 实例对象,类对象,元类对象(1)

    OC对象的分类 OC对象主要分为三类:instance(实例对象),class (类对象),meta-class(...

  • Swift 和 OC 混编遇到的一些问题

    Swift和OC混编中, 有时候OC通过字符串生成Class. 然后通过[[Class alloc] init]生...

  • OC运行时

    我个人对OC的理解就是:动态获取OC Class的属性和方法,从而动态改变Class方法和属性。之前学习Java的...

  • oc对象的种类

    oc对象:instance对象,class对象,meta-class 对象 instance对象 isa 其他成员...

  • Swift_2018-01-02

    OC: 面向对象。swift: 面向协议,struct 替代OC中类class。 资源: https://sw...

  • (一)OC语法01

    1、OC对象的分类 instance class meta-class 2、isa和superclass 3、实例...

  • iOS OC对象的本质

    先来一张OC对象的关系图 oc对象关系图 1、oc对象包括instance对象、class对象、metaclass...

网友评论

    本文标题:OC追根溯源之Class

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