从源码看本质

源代码:

@interface XKPerson ()@property (copy, nonatomic) NSString *name;@end@implementation XKPerson+ (instancetype)personWithName:(NSString *)name {XKPerson *p = [XKPerson new];p.name = name;return p;
}

转化成cpp,整理相关代码:

// 对象信息的实际存储者
struct _class_ro_t {unsigned int flags;unsigned int instanceStart;unsigned int instanceSize;const unsigned char *ivarLayout;const char *name;const struct _method_list_t *baseMethods;const struct _objc_protocol_list *baseProtocols;const struct _ivar_list_t *ivars;const unsigned char *weakIvarLayout;const struct _prop_list_t *properties;
};// 定义了XKPerson的元类
static struct _class_ro_t _OBJC_METACLASS_RO_$_XKPerson = {1, sizeof(struct _class_t), sizeof(struct _class_t), 0, "XKPerson",(const struct _method_list_t *)&_OBJC_$_CLASS_METHODS_XKPerson,0, 0, 0, 0,
};// 定义了XKPerson的类对象
static struct _class_ro_t _OBJC_CLASS_RO_$_XKPerson = {0, __OFFSETOFIVAR__(struct XKPerson, _name), sizeof(struct XKPerson_IMPL), 0, "XKPerson",(const struct _method_list_t *)&_OBJC_$_INSTANCE_METHODS_XKPerson,0, (const struct _ivar_list_t *)&_OBJC_$_INSTANCE_VARIABLES_XKPerson,0, 0,
};// 对象的管理者
struct _class_t {// 传说中的isastruct _class_t *isa;// 传说中的superclassstruct _class_t *superclass;// 缓存相关void *cache;// 暂不使用void *vtable;// 对象信息的实际保存者struct _class_ro_t *ro;
};struct _class_t OBJC_METACLASS_$_NSObject;// 是_class_t,用于管理_XKPerson元类
struct _class_t OBJC_METACLASS_$_XKPerson = {0, // &OBJC_METACLASS_$_NSObject,0, // &OBJC_METACLASS_$_NSObject,0, // (void *)&_objc_empty_cache,0, // unused, was (void *)&_objc_empty_vtable,&_OBJC_METACLASS_RO_$_XKPerson,
};struct _class_t OBJC_CLASS_$_NSObject;// 是_class_t,管理XKPerson的类对象
struct _class_t OBJC_CLASS_$_XKPerson __attribute__ ((used, section ("__DATA,__objc_data"))) = {0, // &OBJC_METACLASS_$_XKPerson,0, // &OBJC_CLASS_$_NSObject,0, // (void *)&_objc_empty_cache,0, // unused, was (void *)&_objc_empty_vtable,&_OBJC_CLASS_RO_$_XKPerson,
};// 真正使用的是_class_t,需要对齐进行初始化
static void OBJC_CLASS_SETUP_$_XKPerson(void ) {// 所有元类的isa指向根源类,也就是metaNSObject// metaNSObject的isa指向跟类对象,也就是classNSObjectOBJC_METACLASS_$_XKPerson.isa = &OBJC_METACLASS_$_NSObject;// 元类的superclass指向父元类OBJC_METACLASS_$_XKPerson.superclass = &OBJC_METACLASS_$_NSObject;OBJC_METACLASS_$_XKPerson.cache = &_objc_empty_cache;// 类对象的isa指向元类OBJC_CLASS_$_XKPerson.isa = &OBJC_METACLASS_$_XKPerson;// 类对象的superclass指向父[类对象]// 跟类对象(classNSObject)指向为nil,触发消息转发机制OBJC_CLASS_$_XKPerson.superclass = &OBJC_CLASS_$_NSObject;OBJC_CLASS_$_XKPerson.cache = &_objc_empty_cache;
}
实例-类对象-元类

为什么 [[obj class] class] 方法获取不到元类

实例对象、类对象、元类的获取代码如下:

NSObject *obj1 = [[NSObject alloc] init];NSObject *obj2 = [[NSObject alloc] init];NSObject *obj3 = [[NSObject alloc] init];NSLog(@"instance address:%p %p %p",obj1, obj2, obj3);NSLog(@"class address: %p %p %p",[obj1 class], [obj2 class], [obj3 class]);NSLog(@"meta class address:%p %p %p",object_getClass([obj1 class]), object_getClass([obj2 class]), object_getClass([obj3 class]));NSLog(@"error meta class address:%p %p %p",[[obj1 class] class], [[obj2 class] class], [[obj3 class] class]);

打印结果:

2020-11-04 09:05:26.264248+0800 XKObjTest[82779:33963605] instance address:0x10285f9a0 0x10285ffb0 0x10285e3d0
2020-11-04 09:05:26.265428+0800 XKObjTest[82779:33963605] class address: 0x7fff9b7d5140 0x7fff9b7d5140 0x7fff9b7d5140
2020-11-04 09:05:26.265520+0800 XKObjTest[82779:33963605] meta class address:0x7fff9b7d50f0 0x7fff9b7d50f0 0x7fff9b7d50f0
2020-11-04 09:05:26.265600+0800 XKObjTest[82779:33963605] error meta class address:0x7fff9b7d5140 0x7fff9b7d5140 0x7fff9b7d5140
Program ended with exit code: 0

我们都知道[[instance class] class]这样是无法获取到元类的,那原因是什么呢?查找 objc 源码得到 class 方法的源码:

+ (Class)class {return self;
}- (Class)class {return object_getClass(self);
}

如上图所示,虽然 class 方法本质是调用 object_getClass,但是类方法 class 确是直接返回自己,也就是类对象,所以类对象无论调用多少次 class 方法,返回的都是类对象自己。

而 object_getClass 的源码如下:

Class object_getClass(id obj)
{if (obj) return obj->getIsa();else return Nil;
}

这个方法直接返回的是 isa 指针的指向,所以可以获取到元类;


http://www.taodudu.cc/news/show-1912777.html

相关文章:

  • id和instancetype
  • Advanced Graphics and Animations for iOS Apps
  • ivar和property
  • bound、frame、position、anchorPoint
  • Java、OC、C/C++中的null
  • iOS:Tagged Pointer
  • sqlite3源码调试
  • 红黑树、B树、B+树各自适用的场景
  • 动态库的隐式链接和显示链接
  • iOS:懒加载符号绑定流程
  • 汇编:call和jmp
  • code review的一些思考
  • iOS:fishhook原理分析
  • mach-O文件结构分析
  • 设备唯一标志的解决方案
  • iOS:主流启动优化方案浅析
  • iOS:segment对齐原则
  • HTTP缓存机制及其在iOS中的应用
  • iOS:SideTable
  • iOS:isa指针
  • iOS底层:PAGEZERO的作用
  • iOS图形学(三):屏幕成像原理
  • iOS图形学(四):iOS中的绘图框架
  • Java基础(一):简介和基础数据类型
  • Java基础(二):面向对象
  • Java:常量池
  • Java基础(三):常用对象
  • Java基础(四):异常处理
  • Java基础(五):多线程
  • Android:权限处理

iOS实例、类、元类相关推荐

  1. php元类,iOS中类、元类、isa详解

    本文是来自@FlyOceanFish的投稿 类相信大家都知道是什么,如果看过runtime的源码或者看过相关的文章对isa肯定也不陌生,不过元类(meta class)大家可能就比较陌生了.不过大家也 ...

  2. Python元类和新型类-对象是类的实例,那类又是谁的实例?

    文章目录 元类 类工厂 初始元类 元类属性 元类作用 面向方面和元类 小结 新型类 新型类VS传统类 静态方法和类方法 特定方法 特定属性 super()方法 小结 元类 既然对象是以类为模板生成的, ...

  3. 深入理解 python 元类

    一.什么的元类 # 思考: # Python 中对象是由实例化类得来的,那么类又是怎么得到的呢? # 疑问: # python 中一切皆对象,那么类是否也是对象?如果是,那么它又是那个类实例化而来的呢 ...

  4. [转]深刻理解Python中的元类(metaclass)

    类也是对象 在理解元类之前,你需要先掌握Python中的类.Python中类的概念借鉴于Smalltalk,这显得有些奇特.在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.在Pytho ...

  5. Python中的元类是什么?

    元类是什么,我们将它们用于什么? #1楼 请注意,此答案适用于2008年编写的Python 2.x,元类在3.x中略有不同. 元类是使"类"工作的秘诀. 新样式对象的默认元类称为& ...

  6. Python中的元类(metaclass)

    类也是对象 在理解元类之前,你需要先掌握Python中的类.Python中类的概念借鉴于Smalltalk,这显得有些奇特.在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.在Pytho ...

  7. 深刻理解Python中的元类(metaclass)以及元类实现单例模式

    在看一些框架源代码的过程中碰到很多元类的实例,看起来很吃力很晦涩:在看python cookbook中关于元类创建单例模式的那一节有些疑惑.因此花了几天时间研究下元类这个概念.通过学习元类,我对pyt ...

  8. python元类简述

    面向对象编程 python 是一门按照面向对象思维设计的一门编程语言,而理解面向对象的语言关键在于一句话,"一切皆对象",函数是一个对象,一个实例是对象,一个类也是对象.如果对象被 ...

  9. python可以实现什么黑科技_Python黑科技之元类

    Python中的类 在理解元类之前,你需要了解Python中的类.Python中的类借鉴自Smalltalk. 在大多数编程语言中,类只是描述对象生成方式的一段代码,在Python里面看起来也是这样. ...

  10. 编写python程序、创建名为class的数据库_Python中的元类(metaclass)以及元类实现单例模式...

    一.理解类也是对象 在理解元类之前,你需要先掌握Python中的类.Python中类的概念借鉴于Smalltalk,这显得有些奇特.在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.在P ...

最新文章

  1. 计算机组成原理——概述3
  2. 在mysql中会话变量前面的字符是什么_在MySQL中仅使用会话变量仅对字符的首次出现执行搜索/替换...
  3. 全球规模最大的全浸没式液冷数据中心落户杭州余杭
  4. jar包直接拷贝到WEB-INF/lib下和以userLibrary引入的区别
  5. 别再搜集面经啦!小夕教你斩下NLP算法岗offer!
  6. C#中的文件流和文本流
  7. WAS生成的文件:javacore.***.txt 、heapdump.***.phd、core.***.dmp、Snap.***.trc
  8. Swift学习笔记(10)--枚举
  9. linux命令行界面如何安装图形化界面
  10. Mysql函数group_concat、find_in_set进行数据库字段值翻译
  11. js:苹果手机页面返回,数据不刷新问题
  12. 单细胞测序在免疫治疗研究中的应用
  13. POM 标签大全详解
  14. 微信小程序上传图片到服务器(java后台以及使用springmvc)
  15. 浏览器主页被劫持篡改了怎么办
  16. java实现汉字判断+中文符号判断
  17. 51单片机点亮LED灯以及实现2盏LED灯的交替闪烁
  18. 【转】互联网产品经理常用软件及工作平台
  19. VOCBENCH声码器评价基准
  20. USACO 3.2 Sweet Butter 香甜的黄油

热门文章

  1. matlab 不同函数间传递结构体数据_VC与Matlab混合编程及复杂数据:结构体传递
  2. redis数据类型之Set
  3. Android开发之ListView中Adapter的优化
  4. 党建活动献爱心,达飞云贷冬日送温暖
  5. 我们总结了每个技术团队都会遇到的 4 个难题 1
  6. 盘点2017年热度很高的编程语言
  7. Chrome Vimium 快捷键
  8. zepto在整个屏幕中左滑动右滑动
  9. 天猫手机一战成名? 塑造品牌 完胜京东
  10. Android之解决太大太多图片造成的oom