当前位置: 移动技术网 > IT编程>移动开发>IOS > class和object_getClass方法区别

class和object_getClass方法区别

2018年12月29日  | 移动技术网IT编程  | 我要评论

色倾天下之新白蛇传,修真高手在现代谢言,彩色世界粤语

一、概述

 

如上图:

1.内存创建一个instance实例对象(person *per),同时会创建一个与之对应的类对象(class perclass)和元类对象(class permeta);

注:实例对象通过calloc可创建多个,但类对象和元类对象在内存中只有一份,只创建一次;

2.对象的本质,其实是c语言的结构体struct,各个对象的内存结构为:

per:isa指针+仅存储person类成员变量的值;

person:isa指针+superclass指针+存储成员变量的类型、名称,协议,对象方法等;

permeta:isa指针+superclass指针+仅存储类方法;

3.isa指向:

per:指向类对象person;

person:指向元类对象permeta;

permeta:指向基类(root,如:nsobject)的元类对象meta(基类的元类对象的isa指向该元类对象自己);

4.superclass指向:

person:指向父类>>基类的类对象指向nil;

permeta:指向父类>>基类的元类对象指向该基类的类对象;

 

二、代码分析

1)通过实例对象per获取类对象

- (void)viewdidload {

    [super viewdidload];

    

    self.per1 = [[person alloc] init];

    self.per2 = [[person alloc] init];

    

    //类对象

    class perclass1 = [self.per1 class];

    class pergetclass2 = object_getclass(self.per1);

    class person = [person class];

    

    //打断点

    nslog(@"---");

}

进入lldb模式:

//所有的对象(包括类对象和实例对象)所属类的名字均为“person”

 

//查看类对象自身地址和self.per成员变量isa的地址值

//p/x:以十六进制输出

如上图说明三个问题:

第一,每个实例对象开辟单独的内存;

第二,同一种类对象仅在内存中开辟一次;

第三,此处class方法和object_getclass无任何区别;

 

2)通过类对象获取元类对象

增加代码:

    //元类对象
    class permeta1 = [pergetclass2 class];
    class permeta2 = object_getclass(pergetclass2);

lldb模式:

  报错:引用的成员变量isa不是结构体或共同体的成员;

 

原因:结构体中的isa变量没有暴露出来,从而无法引用; 

 

 解决:自定义相同结构体,并将对象强制转换

//添加代码

struct lyb_objc_class {
    class _nonnull isa;
};

struct lyb_objc_class *pergetclass3 = (__bridge struct lyb_objc_class *)object_getclass(self.per1);

 

//lldb模式:

 

说明:

1.pergetclass2和pergetclass3指的是同一个类对象;

2.permeta1的地址跟pergetclass2和pergetclass3的地址是相同的,说明此时class并没有返回元类对象,依然是类对象;

3.permeta2的地址和pergetclass3->isa指向的地址相同,说明object_getclass返回的是元类对象;

4.元类对象的类名称和类对象的一样,依然是person;

 

3)通过元类对象获取基类的元类对象

//添加代码

    struct lyb_objc_class *permeta3 = (__bridge struct lyb_objc_class *)object_getclass(pergetclass2);

    //还是permeta2

    class rootmeta1 = [permeta2 class];

    //基类(nsobject)的元类对象

    class rootmeta2 = object_getclass(permeta2);

//lldb模式: 

说明:

1.class返回的依然是元类对象自身,object_getclass返回的是基类的元类对象;

2.基类的元类对象的类名跟类对象的一样,为nsobject;

 

三、结论

当消息对象为实例对象instance时,class与object_getclass返回的对象地址一样;当消息对象为类对象,或元类对象时,class返回的消息对象本身,而object_getclass返回的是下一个对象;

原因:因为class返回的是self,而object_getclass返回的是isa指向的对象;

说明:以上源码查找在github上有演示;

 

github

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网