美文网首页
oc的类方法与实例方法的底层实现&元类到底是个什么鬼

oc的类方法与实例方法的底层实现&元类到底是个什么鬼

作者: 无边小猪 | 来源:发表于2016-09-02 18:23 被阅读0次

以一份代码为例

//hello.h
@interfacehelloA : NSMutableString
- (void)instanceFunctionA;
+ (void)classFunctionA;
@end
@interfacehelloB : helloA
- (void)instanceFunctionB;
+ (void)classFunctionB;
@end
//hello.m
#import"hello.h"
@implementationhelloA
- (void)instanceFunctionA;
{}
+ (void)classFunctionA;
{}
@end
@implementationhelloB
- (void)instanceFunctionB;
{}
+ (void)classFunctionB;
{}
@end

使用命令clang -rewrite-objc hello.m之后可以得到源码,源码量很大不必都看,可以找出如下关键部分:

staticstruct_class_ro_t _OBJC_METACLASS_RO_$_helloA__attribute__((used, section ("__DATA,__objc_const"))) = {
        1,sizeof(struct_class_t),sizeof(struct_class_t),
        (unsignedint)0,
        0,
        "helloA",
        (conststruct_method_list_t *)&_OBJC_$_CLASS_METHODS_helloA,
        0,
        0,
        0,
        0,
};
staticstruct_class_ro_t _OBJC_CLASS_RO_$_helloA__attribute__((used, section ("__DATA,__objc_const"))) = {
        0,sizeof(structhelloA_IMPL),sizeof(structhelloA_IMPL),
        (unsignedint)0,
        0,
        "helloA",
        (conststruct_method_list_t         *)&_OBJC_$_INSTANCE_METHODS_helloA,
        0,
        0,
        0,
        0,
}

从上述代码中可以明显的看出helloA是结构_class_ro_t的对象,分别定义了类 OBJC_CLASS_RO$_helloA和元类OBJC_METACLASS_RO$_helloA,_class_ro_t结构如下

struct_class_ro_t {
unsignedintflags;
unsignedintinstanceStart;
unsignedintinstanceSize;
unsignedintreserved;
constunsignedchar*ivarLayout;
constchar*name;
conststruct_method_list_t *baseMethods;
conststruct_objc_protocol_list *baseProtocols;
conststruct_ivar_list_t *ivars;
constunsignedchar*weakIvarLayout;
conststruct_prop_list_t *properties;
};

其实这就是所谓的NSObject中的isaobjc_class结构,下面是objc_class的结构,看看是不是一样

structobjc_class {
Class isa  OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class                                        OBJC2_UNAVAILABLE;
constchar*name                                         OBJC2_UNAVAILABLE;
longversion                                             OBJC2_UNAVAILABLE;
longinfo                                                OBJC2_UNAVAILABLE;
longinstance_size                                       OBJC2_UNAVAILABLE;
structobjc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
structobjc_method_list **methodLists                    OBJC2_UNAVAILABLE;
structobjc_cache *cache                                 OBJC2_UNAVAILABLE;
structobjc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;

所以说类和元类都是对象,这样便可以理解了,而OBJC_METACLASS_RO$_helloA和OBJC_CLASS_RO$_helloA唯一不同的参数就是conststruct_method_list_t *baseMethods;一个是&OBJC$_CLASS_METHODS_helloA一个是&OBJC$_INSTANCE_METHODS_helloA,我们再来看这个的实现:

staticstruct/*_method_list_t*/{
unsignedintentsize;// sizeof(struct _objc_method)
unsignedintmethod_count;
struct_objc_method method_list[1];
} _OBJC_$_INSTANCE_METHODS_helloA__attribute__((used, section ("__DATA,__objc_const"))) = {
        sizeof(_objc_method),
        1,
        {{(structobjc_selector *)"instanceFunctionA","v16@0:8",         (void*)_I_helloA_instanceFunctionA}}
};
staticstruct/*_method_list_t*/{
        unsignedintentsize;// sizeof(struct _objc_method)
        unsignedintmethod_count;
        struct_objc_method method_list[1];
} _OBJC_$_CLASS_METHODS_helloA__attribute__((used, section ("__DATA,__objc_const"))) = {
        sizeof(_objc_method),
        1,
        {{(structobjc_selector *)"classFunctionA","v16@0:8", (void*)_C_helloA_classFunctionA}}
};

这正是我们定义的一个类方法和一个实例方法,由此可以得知,类方法实现与元类之中,实例方法实现与类之中。之前一度不明白为什么要存在元类这样一个东西,但在发现这可能是元类存在的主要目的。
说到runtime我们经常会看到一张图

2900342-264a14f13872b8c1.jpg

这张图总是很让人迷惑,但是看了下述代码你可能会对这幅图的概念清晰起来

staticvoidOBJC_CLASS_SETUP_$_helloA(void) {
        OBJC_METACLASS_$_helloA.isa = &OBJC_METACLASS_$_NSObject;
        OBJC_METACLASS_$_helloA.superclass = &OBJC_METACLASS_$_NSMutableString;
        OBJC_METACLASS_$_helloA.cache = &_objc_empty_cache;
        OBJC_CLASS_$_helloA.isa = &OBJC_METACLASS_$_helloA;
        OBJC_CLASS_$_helloA.superclass = &OBJC_CLASS_$_NSMutableString;
        OBJC_CLASS_$_helloA.cache = &_objc_empty_cache;
}
staticvoidOBJC_CLASS_SETUP_$_helloB(void) {
        OBJC_METACLASS_$_helloB.isa = &OBJC_METACLASS_$_NSObject;
        OBJC_METACLASS_$_helloB.superclass =                 &OBJC_METACLASS_$_helloA;
        OBJC_METACLASS_$_helloB.cache = &_objc_empty_cache;
        OBJC_CLASS_$_helloB.isa = &OBJC_METACLASS_$_helloB;
        OBJC_CLASS_$_helloB.superclass = &OBJC_CLASS_$_helloA;
        OBJC_CLASS_$_helloB.cache = &_objc_empty_cache;
}

这是helloA和helloB装载方法
其中isa指元类,superclass指父类我们可以简化得到以下内容
helloB类的元类是helloB元类,helloB类的父类是helloA类
helloB元类的元类是NSObject元类,helloB元类的父类是helloA元类
helloA类的元类是helloA元类,helloA类的父类是NSMutableString类
helloA元类的元类是NSObject元类,helloA元类的父类是NSMutableString元类

相关文章

  • oc的类方法与实例方法的底层实现&元类到底是个什么鬼

    以一份代码为例 使用命令clang -rewrite-objc hello.m之后可以得到源码,源码量很大不必都看...

  • OC消息发送机制

    OC的方法调用都是通过消息发送这种机制来实现的。当调用一个实例方法或者类方法时,底层实现是实例对象或者类对象调用o...

  • iOS类与方法底层实现初探

    前言: 学习了OC之后,我们知道类和方法的定义和使用,为了更好理解类和方法,这里我将初步解析iOS类与方法底层实现...

  • IOS精选面试题(三)

    OC调用一个方法底层做了哪些事 一:如果是调用实例方法,通过实例对象的isa指针找到类对象,在类对象的方法缓存(c...

  • OC&iOS

    OC语言基础 1.类与对象 类方法 OC的类方法只有2种:静态方法和实例方法两种 在OC中,只要方法声明在@int...

  • Objective-C 类与对象

    类方法 OC 中类的方法只有类的静态方法和类的实例方法 OC 中的方法只要声明在 @interface 里,就可以...

  • 对象、类对象、元类对象&消息传递机制

    类对象:存储实例方法列表等信息。 元类对象:存储类方法列表等信息。 调用的类方法没有对应的实现,则会调用同名的实例...

  • iOS运行时中isa指针的本质

    在OC中,因为类也是一个对象,所以也必须是另外一个类的实例,这个类就是元类(metaclass)。元类保存了类方法...

  • swift方法

    oc中只有类可以定义方法,swift类/结构体/枚举都能定义方法 swift的类型方法类似oc的类方法 实例方法(...

  • From Objective-C to Ruby(4)-类和模块

    类 定义类 OC: ruby: 初始化方法 OC: ruby: 实例变量和属性 OC: ruby: 类方法和对象方...

网友评论

      本文标题:oc的类方法与实例方法的底层实现&元类到底是个什么鬼

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