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

以一份代码为例

//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元类

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,063评论 6 510
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,805评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,403评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,110评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,130评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,877评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,533评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,429评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,947评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,078评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,204评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,894评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,546评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,086评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,195评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,519评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,198评论 2 357

推荐阅读更多精彩内容