iOS下RunTime分析三(扩展C++源码)
接上一篇文章:iOS下RunTime分析一(OC文件编译为C++)
这里主要是解释iOS下RunTime分析一(OC文件编译为C++)中的第5点疑问。
这里看类别部分的OC源码
头文件:
@interface MyObject (Extensions)
- (void)methodA;
- (void)methodB:(NSString *)str;
@property (nonatomic, strong) NSObject *methodObj;
@end
@interface MyObject (Common)
- (void)methodCommon;
+ (void)classCommonMethod;
@end
源文件:
@implementation MyObject (Extensions)
- (void)methodA
{
return;
}
- (void)methodB:(NSString *)str
{
return;
}
- (NSObject *)methodObj
{
return nil;
}
- (void)setMethodObj:(NSObject *)methodObj
{
return;
}
@end
@implementation MyObject (Common)
- (void)methodCommon
{
return;
}
+ (void)classCommonMethod
{
return;
}
@end
现在来看下编译成C++之后的源代码,与RunTime分析一相似的部分,不在重新写了。
会生成一个_category_t的结构体:
struct _category_t {
const char *name;
struct _class_t *cls;
const struct _method_list_t *instance_methods;
const struct _method_list_t *class_methods;
const struct _protocol_list_t *protocols;
const struct _prop_list_t *properties;
};
以及相关的静态结构体对象:
(used, section ("__DATA,__objc_const"))
static struct /*_method_list_t*/ {
unsigned int entsize; // sizeof(struct _objc_method)
unsigned int method_count;
struct _objc_method method_list[4];
} _OBJC_$_CATEGORY_INSTANCE_METHODS_MyObject_$_Extensions = {
sizeof(_objc_method),
4,
{ {(struct objc_selector *)"methodA", "v16@0:8", (void *)_I_MyObject_Extensions_methodA},
{(struct objc_selector *)"methodB:", "v24@0:8@16", (void *)_I_MyObject_Extensions_methodB_},
{(struct objc_selector *)"methodObj", "@16@0:8", (void *)_I_MyObject_Extensions_methodObj},
{(struct objc_selector *)"setMethodObj:", "v24@0:8@16", (void *)_I_MyObject_Extensions_setMethodObj_} }
};
(used, section ("__DATA,__objc_const"))
static struct /*_prop_list_t*/ {
unsigned int entsize; // sizeof(struct _prop_t)
unsigned int count_of_properties;
struct _prop_t prop_list[1];
} _OBJC_$_PROP_LIST_MyObject_$_Extensions = {
sizeof(_prop_t),
1,
{ {"methodObj","T@\"NSObject\",&,N"}}
};
(used, section ("__DATA,__objc_const"))
static struct _category_t _OBJC_$_CATEGORY_MyObject_$_Extensions =
{
"MyObject",
0, // &MyObject,
&_OBJC_$_CATEGORY_INSTANCE_METHODS_MyObject_$_Extensions,
0,
0,
(const struct _prop_list_t *)&_OBJC_$_PROP_LIST_MyObject_$_Extensions,
};
static void OBJC_CATEGORY_SETUP_$_MyObject_$_Extensions(void ) {
_OBJC_$_CATEGORY_MyObject_$_Extensions.cls = &MyObject;
}
以上生成的是@interface MyObject (Extensions)这个类别中的相关结构体对象。
下面看下@interface MyObject (Common)中的结构体对象:
OBJC_CATEGORY_SETUP_$_MyObject_
static struct /*_method_list_t*/ {
unsigned int entsize; // sizeof(struct _objc_method)
unsigned int method_count;
struct _objc_method method_list[1];
} _OBJC_$_CATEGORY_INSTANCE_METHODS_MyObject_$_Common = {
sizeof(_objc_method),
1,
{ {"methodCommon", "v16@0:8", (void *)_I_MyObject_Common_methodCommon} }
};
OBJC_CATEGORY_SETUP_$_MyObject_
static struct /*_method_list_t*/ {
unsigned int entsize; // sizeof(struct _objc_method)
unsigned int method_count;
struct _objc_method method_list[1];
} _OBJC_$_CATEGORY_CLASS_METHODS_MyObject_$_Common = {
sizeof(_objc_method),
1,
{ {"classCommonMethod", "v16@0:8", (void*)_C_MyObject_Common_classCommonMethod}}
};
OBJC_CATEGORY_SETUP_$_MyObject_
static struct _category_t _OBJC_$_CATEGORY_MyObject_$_Common =
{
"MyObject",
0, // &MyObject,
&_OBJC_$_CATEGORY_INSTANCE_METHODS_MyObject_$_Common,
)&_OBJC_$_CATEGORY_CLASS_METHODS_MyObject_$_Common,
0,
0,
};
static void OBJC_CATEGORY_SETUP_$_MyObject_$_Common(void ) {
_OBJC_$_CATEGORY_MyObject_$_Common.cls = &MyObject;
}
以上两个结构体对象都是通过OBJC_CATEGORY_SETUP_$_MyObject_$_Extensions和OBJC_CATEGORY_SETUP_$_MyObject_$_Common与MyObject这个类关联起来的。
static void *OBJC_CATEGORY_SETUP[] = {
(void *)&OBJC_CATEGORY_SETUP_$_MyObject_$_Extensions,
(void *)&OBJC_CATEGORY_SETUP_$_MyObject_$_Common,
};
(used, section ("__DATA, __objc_catlist,regular,no_dead_strip"))
static struct _category_t *L_OBJC_LABEL_CATEGORY_$ [2] = {
&_OBJC_$_CATEGORY_MyObject_$_Extensions,
&_OBJC_$_CATEGORY_MyObject_$_Common,
};
static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };
总结
每个category都是一个结构体的对象,只是_category_t中的isa指向的是MyObject的对象。只是现在有一个疑问,当调用category中的方法时,MyObject是如何找到该方法的?