實(shí)例對(duì)象:就是我們通常的類的實(shí)例化的對(duì)象比如
Obj * obj = [Obj new];
,那么這個(gè)obj
就是一個(gè)實(shí)例對(duì)象
類對(duì)象:這個(gè)時(shí)候是否有點(diǎn)奇怪拍霜,其實(shí)類也是一個(gè)對(duì)象嘱丢,比如Obj
其實(shí)也是一個(gè)對(duì)象
元類:其實(shí)就是 類對(duì)象的isa指向的類。
- 可能前面的定義有點(diǎn)模糊祠饺,下面我們看看越驻,runtime里面的 實(shí)例的結(jié)構(gòu)體和 類的結(jié)構(gòu)體
----------------------------------------------------
//類的實(shí)例
typedef struct objc_object *id;
/// Represents an instance of a class.
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
這里有個(gè)isa 指針,指向的就是 當(dāng)前實(shí)例的類對(duì)象
----------------------------------------------------
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY; //
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE;//父類
const char *name OBJC2_UNAVAILABLE;//類名
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;//實(shí)例大小
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE;//成員變量列表
struct objc_method_list **methodLists OBJC2_UNAVAILABLE;//方法列表
struct objc_cache *cache OBJC2_UNAVAILABLE;//方法緩存
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;//協(xié)議列表
#endif
} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */
這里也是有個(gè)isa 指針道偷,其實(shí)這個(gè)isa 指向的就是 **元類**
----------------------------------------------------
2缀旁、下面我們來看一個(gè)例子,方便更好的來理解元類
的概念
同時(shí)我們首先理解幾個(gè)知識(shí)點(diǎn)
object_getClass(實(shí)例對(duì)象) == [實(shí)例對(duì)象 class]
[類對(duì)象 class] == 類對(duì)象
object_getClass(類對(duì)象) == 類對(duì)象的isa == 元類
object_getClass(類對(duì)象) != [類對(duì)象 class]
添加方法勺鸦,其實(shí)是在 類對(duì)象/實(shí)例對(duì)象
中的isa指針的類中添加
首先定義一個(gè) Obj的類
----------------------------------------------------
@interface Obj : NSObject
//實(shí)例方法
- (void)print1;
//類對(duì)象方法
+ (void)classPrint;
@end
@implementation Obj
//這里不去實(shí)現(xiàn)它并巍,后面我們會(huì)通過runtime的知識(shí)添加方法
@end
下面我們切換當(dāng)控制器中
----------------------------------------------------
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
Obj * obj = [Obj new];
Class class11 = object_getClass(obj);
Class class12 = [obj class]; //這個(gè)是獲取當(dāng)前的類的對(duì)象,實(shí)例是就是isa指向的類對(duì)象换途,但是類對(duì)象指向確是自己本身
NSLog(@"class1 :%p,class2 = %p",class11,class12);
//class1 :0x1077b8f00,class2 = 0x1077b8f00
Class class21 = object_getClass(class11);//Son的Class的元類
Class class22 = [class12 class];//還是本身Son的Class
Class classMeta= objc_getMetaClass(object_getClassName(obj));//Son的Class元類
NSLog(@"class1 :%p,class2 = %p,classMeta = %p",class21,class22,classMeta);
//class1 :0x1077b8ed8,class2 = 0x1077b8f00,classMeta = 0x1077b8ed8
//在給對(duì)象或者類添加方法的時(shí)候懊渡,其實(shí)是給isa 指向的類添加方法,就是說 一個(gè)普通的對(duì)象是給它的class添加方法军拟,而 一個(gè)普通的類對(duì)象剃执,需要添加方法其實(shí)是給它isa指向的 元類添加方法
//給obj實(shí)例對(duì)象 添加 方法
class_addMethod(class11, @selector(print1), (IMP)IMPFunc, NULL);
[obj print1];
//給obj的類對(duì)象添加方法
class_addMethod(class21, @selector(classPrint), (IMP)IMPMetaClassFunc, NULL);
[Obj classPrint];
}
void IMPFunc(id self ,SEL cmd) {
NSLog(@"print1");
}
void IMPMetaClassFunc(id self ,SEL cmd) {
NSLog(@"IMPMetaClassFunc");
}