刨根问底Objective-C Runtime(2)- Object & Class & Meta Class
2014-11-19 14:35
726 查看
原文地址:http://chun.tips/blog/2014/11/05/bao-gen-wen-di-objective%5Bnil%5Dc-runtime-(2)%5Bnil%5D-object-and-class-and-meta-class/
上一篇笔记讲述了objcruntime中Self和Super的细节,本篇笔记主要是讲述objcruntime中关于Object&Class&
MetaClass的细节。
下面代码的运行结果是?
@interfaceSark:NSObject
@end
@implementationSark
@end
intmain(intargc,constchar*argv[]){
@autoreleasepool{
BOOLres1=[(id)[NSObjectclass]isKindOfClass:[NSObjectclass]];
BOOLres2=[(id)[NSObjectclass]isMemberOfClass:[NSObjectclass]];
BOOLres3=[(id)[Sarkclass]isKindOfClass:[Sarkclass]];
BOOLres4=[(id)[Sarkclass]isMemberOfClass:[Sarkclass]];
NSLog(@"%d%d%d%d",res1,res2,res3,res4);
}
return0;
}
[/code]
运行结果为:
2014-11-0514:45:08.474Test[9412:721945]1000
[/code]
什么是id
id在objc.h中定义如下:
///Apointertoaninstanceofaclass.
typedefstructobjc_object*id;
[/code]
就像注释中所说的这样id是指向一个objc_object结构体的指针。
那么objc_object又是什么呢
objc_object在objc.h中定义如下:
///Representsaninstanceofaclass.
structobjc_object{
Classisa;
};
[/code]
这个时候我们知道Objective-C中的object在最后会被转换成C的结构体,而在这个struct中有一个isa指针,指向它的类别Class。
那么什么是Class呢
在objc.h中定义如下:
///AnopaquetypethatrepresentsanObjective-Cclass.
typedefstructobjc_class*Class;
[/code]
我们可以看到Class本身指向的也是一个C的struct
继续看在runtime.h中
structobjc_class{
ClassisaOBJC_ISA_AVAILABILITY;
#if!__OBJC2__
Classsuper_classOBJC2_UNAVAILABLE;
constchar*nameOBJC2_UNAVAILABLE;
longversionOBJC2_UNAVAILABLE;
longinfoOBJC2_UNAVAILABLE;
longinstance_sizeOBJC2_UNAVAILABLE;
structobjc_ivar_list*ivarsOBJC2_UNAVAILABLE;
structobjc_method_list**methodListsOBJC2_UNAVAILABLE;
structobjc_cache*cacheOBJC2_UNAVAILABLE;
structobjc_protocol_list*protocolsOBJC2_UNAVAILABLE;
#endif
}OBJC2_UNAVAILABLE;
[/code]
该结构体中,isa指向所属Class,super_class指向父类别。
继续看
下载objc源代码,在objc-runtime-new.h中,我们发现
structobjc_class:objc_object{
//ClassISA;
Classsuperclass;
...
...
}
[/code]
豁然开朗,我们看到在Objective-C的设计哲学中,一切都是对象。Class在设计中本身也是一个对象。而这个Class对象的对应的类,我们叫它
MetaClass
根据上面的描述,我们可以把
当我们发送一个消息给一个NSObject对象时,这条消息会在对象的类的方法列表里查找
当我们发送一个消息给一个类时,这条消息会在类的MetaClass的方法列表里查找
而MetaClass本身也是一个Class,它跟其他Class一样也有自己的isa和super_class指针。看下图:
每个Class都有一个isa指针指向一个唯一的MetaClass
每一个MetaClass的isa指针都指向最上层的MetaClass(图中的NSObject的MetaClass)
每一个MetaClass的superclass指针指向它原本Class的SuperClass的MetaClass。
最上层的NSObjectClass的superclass指向nil
为了更加清楚的知道整个函数调用过程,我们使用
BOOLres1=((BOOL(*)(id,SEL,Class))(void*)objc_msgSend)((id)((Class(*)(id,SEL))(void*)objc_msgSend)((id)objc_getClass("NSObject"),sel_registerName("class")),sel_registerName("isKindOfClass:"),((Class(*)(id,SEL))(void*)objc_msgSend)((id)objc_getClass("NSObject"),sel_registerName("class")));
BOOLres2=((BOOL(*)(id,SEL,Class))(void*)objc_msgSend)((id)((Class(*)(id,SEL))(void*)objc_msgSend)((id)objc_getClass("NSObject"),sel_registerName("class")),sel_registerName("isMemberOfClass:"),((Class(*)(id,SEL))(void*)objc_msgSend)((id)objc_getClass("NSObject"),sel_registerName("class")));
BOOLres3=((BOOL(*)(id,SEL,Class))(void*)objc_msgSend)((id)((Class(*)(id,SEL))(void*)objc_msgSend)((id)objc_getClass("Sark"),sel_registerName("class")),sel_registerName("isMemberOfClass:"),((Class(*)(id,SEL))(void*)objc_msgSend)((id)objc_getClass("NSObject"),sel_registerName("class")));
BOOLres4=((BOOL(*)(id,SEL,Class))(void*)objc_msgSend)((id)((Class(*)(id,SEL))(void*)objc_msgSend)((id)objc_getClass("Sark"),sel_registerName("class")),sel_registerName("isMemberOfClass:"),((Class(*)(id,SEL))(void*)objc_msgSend)((id)objc_getClass("NSObject"),sel_registerName("class")));
[/code]
先看前两个调用:
最外层是
函数第一个参数是
函数第二个参数是转发的selector
函数第三个参数是
我们注意到第一个参数和第三个参数对应重写的是
NSObjectClass发送@selector(class)这个消息
打开objc源代码,在Object.mm中发现
+(Class)class{
returnself;
}
[/code]
所以即返回Class类的对象本身。看如下输出:
NSLog(@"%p",[NSObjectclass]);
NSLog(@"%p",[NSObjectclass]);
2014-11-0518:48:30.939Test[11682:865988]0x7fff768d40f0
2014-11-0518:48:30.940Test[11682:865988]0x7fff768d40f0
[/code]
继续打开objc源代码,在Object.mm中,我们发现
-(BOOL)isKindOf:aClass
{
Classcls;
for(cls=isa;cls;cls=cls->superclass)
if(cls==(Class)aClass)
returnYES;
returnNO;
}
[/code]
对着上面MetaClass的图和实现,我们可以看出
当NSObjectClass对象第一次进行比较时,得到它的isa为NSObject的MetaClass,这个时候NSObjectMetaClass和NSObjectClass不相等。
然后取NSObject的MetaClass的Superclass,这个时候又变成了NSObjectClass,所以返回相等
所以上述第一个输出结果是YES。
我们在看下‘isMemberOfClass’的实现:
-(BOOL)isMemberOf:aClass
{
returnisa==(Class)aClass;
}
[/code]
综上所述,当前的isa指向NSObject的MetaClass,所以和NSObjectClass不相等。
所以上述第二个输出结果为NO。
继续看后面两个调用:
SarkClass的isa指向的是Sark的MetaClass,和SarkClass不相等
SarkMetaClass的superclass指向的是NSObjectMetaClass,和SarkClass不相等
NSObjectMetaClass的superclass指向NSObjectClass,和SarkClass不相等
NSObjectClass的superclass指向nil,和SarkClass不相等
所以后面两个调用的结果都输出为NO。
上一篇笔记讲述了
MetaClass的细节。
习题内容
下面代码的运行结果是?[/code]
运行结果为:
[/code]
这里先看几个概念
什么是id
id在objc.h中定义如下:
[/code]
就像注释中所说的这样id是指向一个objc_object结构体的指针。
id 这个struct的定义本身就带了一个*,所以我们在使用其他NSObject类型的实例时需要在前面加上*,而使用id时却不用。
那么objc_object又是什么呢
objc_object在objc.h中定义如下:
[/code]
这个时候我们知道Objective-C中的object在最后会被转换成C的结构体,而在这个struct中有一个isa指针,指向它的类别Class。
那么什么是Class呢
在objc.h中定义如下:
[/code]
我们可以看到Class本身指向的也是一个C的struct
objc_class。
继续看在runtime.h中
objc_class定义如下:
[/code]
该结构体中,isa指向所属Class,super_class指向父类别。
继续看
下载objc源代码,在objc-runtime-new.h中,我们发现
objc_class有如下定义:
[/code]
豁然开朗,我们看到在Objective-C的设计哲学中,一切都是对象。Class在设计中本身也是一个对象。而这个Class对象的对应的类,我们叫它
Meta Class。即Class结构体中的isa指向的就是它的
Meta Class。
MetaClass
根据上面的描述,我们可以把
Meta Class理解为
一个Class对象的Class。简单的说:
当我们发送一个消息给一个NSObject对象时,这条消息会在对象的类的方法列表里查找
当我们发送一个消息给一个类时,这条消息会在类的MetaClass的方法列表里查找
而MetaClass本身也是一个Class,它跟其他Class一样也有自己的isa和super_class指针。看下图:
每个Class都有一个isa指针指向一个唯一的MetaClass
每一个MetaClass的isa指针都指向最上层的MetaClass(图中的NSObject的MetaClass)
最上层的Meta Class的isa指针指向自己,形成一个回路
每一个MetaClass的superclass指针指向它原本Class的SuperClass的MetaClass。
但是最上层的Meta Class的SuperClass指向NSObjectClass本身
最上层的NSObjectClass的superclass指向nil
解惑
为了更加清楚的知道整个函数调用过程,我们使用clang -rewrite-objcmain.m重写,可获得如下代码:
BOOLres2=((BOOL(*)(id,SEL,Class))(void*)objc_msgSend)((id)((Class(*)(id,SEL))(void*)objc_msgSend)((id)objc_getClass("NSObject"),sel_registerName("class")),sel_registerName("isMemberOfClass:"),((Class(*)(id,SEL))(void*)objc_msgSend)((id)objc_getClass("NSObject"),sel_registerName("class")));
BOOLres3=((BOOL(*)(id,SEL,Class))(void*)objc_msgSend)((id)((Class(*)(id,SEL))(void*)objc_msgSend)((id)objc_getClass("Sark"),sel_registerName("class")),sel_registerName("isMemberOfClass:"),((Class(*)(id,SEL))(void*)objc_msgSend)((id)objc_getClass("NSObject"),sel_registerName("class")));
BOOLres4=((BOOL(*)(id,SEL,Class))(void*)objc_msgSend)((id)((Class(*)(id,SEL))(void*)objc_msgSend)((id)objc_getClass("Sark"),sel_registerName("class")),sel_registerName("isMemberOfClass:"),((Class(*)(id,SEL))(void*)objc_msgSend)((id)objc_getClass("NSObject"),sel_registerName("class")));
[/code]
先看前两个调用:
最外层是
objc_msgSend函数,转发消息。
函数第一个参数是
(id)((Class
(*)(id,SEL))(void*)objc_msgSend)((id)objc_getClass("NSObject"),sel_registerName("class"))
函数第二个参数是转发的selector
函数第三个参数是
((Class
(*)(id,SEL))(void*)objc_msgSend)((id)objc_getClass("NSObject"),sel_registerName("class"))
我们注意到第一个参数和第三个参数对应重写的是
[NSObject class],即使用
objc_msgSend向
NSObjectClass发送@selector(class)这个消息
打开objc源代码,在Object.mm中发现
+ (Class)class实现如下:
returnself;
}
[/code]
所以即返回Class类的对象本身。看如下输出:
NSLog(@"%p",[NSObjectclass]);
2014-11-0518:48:30.939Test[11682:865988]0x7fff768d40f0
2014-11-0518:48:30.940Test[11682:865988]0x7fff768d40f0
[/code]
继续打开objc源代码,在Object.mm中,我们发现
isKindOfClass的实现如下:
{
Classcls;
for(cls=isa;cls;cls=cls->superclass)
if(cls==(Class)aClass)
returnYES;
returnNO;
}
[/code]
对着上面MetaClass的图和实现,我们可以看出
当NSObjectClass对象第一次进行比较时,得到它的isa为NSObject的MetaClass,这个时候NSObjectMetaClass和NSObjectClass不相等。
然后取NSObject的MetaClass的Superclass,这个时候又变成了NSObjectClass,所以返回相等
所以上述第一个输出结果是YES。
我们在看下‘isMemberOfClass’的实现:
{
returnisa==(Class)aClass;
}
[/code]
综上所述,当前的isa指向NSObject的MetaClass,所以和NSObjectClass不相等。
所以上述第二个输出结果为NO。
继续看后面两个调用:
SarkClass的isa指向的是Sark的MetaClass,和SarkClass不相等
SarkMetaClass的superclass指向的是NSObjectMetaClass,和SarkClass不相等
NSObjectMetaClass的superclass指向NSObjectClass,和SarkClass不相等
NSObjectClass的superclass指向nil,和SarkClass不相等
所以后面两个调用的结果都输出为NO。
下一篇博客的主要分享的内容是关于
ObjectiveCRuntime中消息和Category的学习笔记。
相关文章推荐
- 刨根问底Objective-C Runtime(2)- Object & Class & Meta Class
- 刨根问底Objective-C Runtime(2)- Object & Class & Meta Class
- 刨根问底Objective-C Runtime(2)- Object & Class & Meta Class
- 《转》Objective-C Runtime(2)- Object & Class & Meta Class
- 刨根问底Objective-C Runtime(1)- Self & Super
- 对象&类&元类(Object & Class & Meta Class)
- 基于QWidget类的动态库在4.8.1隐式调用时出现staticMetaObject' of dllimport'd class的解决办法
- Objective-C的object、class、meta-class
- 刨根问底Objective-C Runtime(1)- Self & Super
- 刨根问底Objective-C Runtime(1)- Self & Super
- RUNTIME_CLASS(xx)->CreateObject()错误Error: Trying to create object which is not DECLARE_DYNCREATE
- 对象&类&元类(Object & Class & Meta Class)
- 刨根问底Objective-C Runtime(1)- Self & Super
- Objective-C - runtime 之 Class 和 Meta Class
- 刨根问底Objective-C Runtime(1)- Self & Super
- 刨根问底Objective-C Runtime(1)- Self & Super
- 详解Objective-C的meta-class ,runtime创建类,添加实例变量
- Qt函数connectSlotsByName(),即"QMetaObject::connectSlotsByName(QObject *o)"的说明
- object of abstract class type "我的类" is not allowed 解决方案
- Unable to find a value for "tStatus" in object of class org.entity.Passport using operator "."