以一份代码为例
//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我们经常会看到一张图
这张图总是很让人迷惑,但是看了下述代码你可能会对这幅图的概念清晰起来
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元类