Objective-C的本质

1、我们编写的Objective-C,底层现实都是C/C++,代码生成步骤如下:

2、在OC中的所有面向对象的实现,都是基于C/C++的数据结构实现的

3、将Objective-C代码转换为C\C++代码

  xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 输出的CPP文件

   注:如果需要链接其他框架,使用-framework参数。比如-framework UIKit

一个OC对象在内存中是如何布局的?

NSObject基类的实现:

子类的实现:

子类的拆解:

1、在OC中的对象,就是 C++中的 struct来实现的

2、每个OC对象中都会有一个 isa 的指针,isa指向的是 objc_class 结构体,如下(旧版OC原码):

通过代码可以看得出在OC2 中已经不能通过  objc_method_list 之类的方式获取方法名、实例、协议之类的了,需要使用新的方法获取

思路:自定义一个和oc源码中 objc_class 结构一样的结构体,然后将对象的isa 强转成我们自定义的那个,再去调用

如下是OC中objc_class的源码(新版OC原码):

新的OC版本中方法、属性、协议相关数据都存在了 bits

通过 bits.data() 返回 class_rw_t 结构,如下:

bits.data() 的实现:

其中需要 通过 & FAST_DATA_MASK 才能获取到真实的地址

整体数据结构图:

OC对象的分类

Objective-C对象主要分为以下3类:

  1> instance对象(实例对象)

  2> class对象(类对象)存储实例方法列表等信息

  3> meta-class对象(元类对象)存储类方法列表等信息

通过下面的代码可以分别获取3种对象:

        NSObject* obj = [[NSObject alloc]init];const char* className = [@"NSObject" cStringUsingEncoding:NSUTF8StringEncoding];// 实例对象NSLog(@"instance: %p",obj);// 类对象NSLog(@"NSObject class: %p", [NSObject class]);// 同上NSLog(@"obj class: %p", [obj class]);// 如果传实例对象,获取到的还是类对象NSLog(@"get class: %p", object_getClass(obj));// 通过类名获取类对象NSLog(@"objcClass: %p", objc_getClass(className));// 元类对象// 必需要传入类对象才能获取元类对象NSLog(@"meta-class: %p", object_getClass([obj class]));// 通过类名获取元类对象NSLog(@"objcMetaClass: %p", objc_getMetaClass(className));// 判断是否是metaClassNSLog(@"isMetaClass1:%i",class_isMetaClass([NSObject class]));  // 0NSLog(@"isMetaClass2:%i",class_isMetaClass([[NSObject class] class])); // 0NSLog(@"isMetaClass3:%i",class_isMetaClass(object_getClass([NSObject class]))); // 1

输出:

2018-09-27 14:39:37.363 OC_isa_supclass[1350:102454] instance: 0x100202b50
2018-09-27 14:39:37.364 OC_isa_supclass[1350:102454] NSObject class: 0x7fff760140f0
2018-09-27 14:39:37.364 OC_isa_supclass[1350:102454] obj class: 0x7fff760140f0
2018-09-27 14:39:37.364 OC_isa_supclass[1350:102454] get class: 0x7fff760140f0
2018-09-27 14:39:37.365 OC_isa_supclass[1350:102454] objcClass: 0x7fff760140f0
2018-09-27 14:39:37.365 OC_isa_supclass[1350:102454] meta-class: 0x7fff76014118
2018-09-27 14:39:37.365 OC_isa_supclass[1350:102454] objcMetaClass: 0x7fff760141182018-09-27 14:49:27.746 OC_isa_supclass[1360:106109] isMetaClass1:02018-09-27 14:49:27.746 OC_isa_supclass[1360:106109] isMetaClass2:02018-09-27 14:49:27.746 OC_isa_supclass[1360:106109] isMetaClass3:1

  1> 需要注意的是 object_getClass 方法,当传入的是实例对象,就会返回类对象,如果传入的是类对象就会返回元类对象

  2> 还有一点就是 [[NSObject class] class] 这样是获取不到元类对象的,这样获取到的还是类对象

   3> 另外里面还有两个 objc_ 开头的方法,分别是获取类对象和元类对象,但它是传入类名字符串就可以了,需要转换成 C语言的char

1、instance对象

instance对象就是通过类alloc出来的对象,每次调用alloc都会产生新的instance对象
object1、object2是NSObject的instance对象(实例对象)

  它们是不同的两个对象,分别占据着两块不同的内存

 instance对象在内存中保存的信息包括:

  1> isa指针

  2> 其它成员变量

2、class对象

objectClass1 ~ objectClass5都是NSObject的class对象(类对象)

 NSObject类对象只有一个,所有实例对象的class属性获取到的都是同一个类对象

class对象在内存中存储的信息主要包括:

  1> isa指针

  2> superclass指针

  3> 类的属性信息(@property)、类的对象方法信息(instance method)

  4> 类的协议信息(protocol)、类的成员变量信息(ivar)

    ....

3、meta-class对象

  

objectMetaClass是NSObject的meta-class对象(元类对象)

  每个类在内存中有且只有一个meta-class对象

  meta-class对象在内存中存储的信息主要包括:

  1> isa指针

   2> superclass指针

   3> 类的类方法信息(class method)

    ...

 注:class 对象和 meta-class 对象都是 Class 类型的,它们其实结构都是一样的,class对象中一样会包含 类方法,只不过那个类方法是 空的而已。

   同样,meta-class对象中也有 类的属性、对象方法、协议、成员变量,不过那些对应的值也都是空

isa指针

上面我们通过源码可以看到每个对象都有一个 isa 指针,isa指针作用是干嘛的呢?

通过上图可以看出:

  1> instance的isa指向class
    当调用对象方法时,通过instance的isa找到class,最后找到对象方法的实现进行调用

  2> class的isa指向meta-class

    当调用类方法时,通过class的isa找到meta-class,最后找到类方法的实现进行调用

class对象的superclass指针

superclass是用于找父类的,比如子类调用某个方法,如果子类中没有,就会去父类找,底层就是通过superclass找到父类的,如下图:

当Student的instance对象要调用Person的对象方法时,会先通过isa找到Student的class,然后通过superclass找到Person的class,最后找到对象方法的实现进行调用

meta-class对象的superclass指针

meta-class中的superclass基本和 class对象中的一样,不过有一点点区别,如图:

  当Student的class要调用Person的类方法时,会先通过isa找到Student的meta-class,然后通过superclass找到Person的meta-class,最后找到类方法的实现进行调用

  有什么区别呢?从这图可能看不出来,区别就是如果基类的meta-class中都找不到类方法,那么它就会去从基类对象里面去找对象方法,OC的底层其实是不区分 对象方法与类方法的。

isa、superclass总结

这张图能够清楚的描述 isa和superclass的作用和关系,下面是备注了一下,看得更加懂点。

  • instance的isa指向的是class对象
  • class的isa指向的是meta-class对象
  • 所有的meta-class的isa指向的都是基类的meta-class对象(重点)
  • class的superclass指向的是父类的class对象,如果没有父类,superclass指针为nil
  • meta-class的superclass指向的是父类的meta-class对象
  • 基类的meta-class的superclass指向的是基类的class对象(重点)

  instance调用对象方法的轨迹:

  实例对象会先通过isa找到class对象,判断里面有没有要调用的方法,如果有就直接调用,没有就会通过class对象中的superclass找到父类,然后在父类中判断是否有该方法,如果还没有就接着往上找。

  class调用类方法的轨迹:

   isa找meta-class,方法不存在,就通过superclass找父类,最后基类mate-class也没有的话还会去基类对象找,这样就会导致调用类方法可能会去调用实例对象的方法

isa指针的一些问题

上面已经说到了instance对象的isa指针指向的是class对象,那就是说instance对象的isa指针内存地址是不是就是class对象的内存地址呢?

如果在以前的32位系统中确实如此,在64位系统中不是的,里面有一个点操作, ISA_MASK

其中arm64和x86架构的这个 ISA_MASK的偏移地址是不一样的,如下图:

class、meta-class对象的本质结构都是struct objc_class,如下图:

  

-----------------------------

本文参考借鉴MJ的教程视频,非常感谢.

转载于:https://www.cnblogs.com/xgao/p/9708163.html

【OC底层】OC对象本质,如 isa, super-class相关推荐

  1. iOS对象本质及isa

    文章目录 前言 一.对象的本质是什么? 1.对象的本质 2.name的set与get方法 二.isa分析 1.联合体 2.位域 3.isa关联指针与类 a.通过掩码来还原类信息 b.通过位运算还原类信 ...

  2. OC底层消息转发机制

    目录 1. 前言 2. 动态方法决议 2.1 实例方法动态决议 2.2 类方法动态决议 3. 消息转发 3.1 快速转发流程 3.2 慢速转发流程 4. 总结 1. 前言 上一篇文章(OC底层方法的本 ...

  3. MJiOS底层笔记--OC对象本质

    本文属笔记性质,主要针对自己理解不太透彻的地方进行记录. 推荐系统直接学习小码哥iOS底层原理班---MJ老师的课确实不错,强推一波. OC对象本质 基于C与C++结构体实现 OC语言如何被编译器编译 ...

  4. 浅谈OC中Block的本质

    Block简介 block是将函数及其执行上下文封装起来的一个对象 在block实现的内部,有很多变量,因为block也是一个对象 其中包含了诸如isa指针,imp指针等对象变量,还有储存其截获变量的 ...

  5. OC底层探索(七) cache_t分析

    cache_t 源码 在OC底层探索(五) 类的结构分析文章中,我们分析objc_class源码时,有提到过其属性 cache_t cache属性的大小为16字节. 那么我们今天就着重分析以下cach ...

  6. OC底层探索(二十二)八大锁

    OC底层文章汇总 锁的种类 在OC中锁分为互斥锁和自旋锁两种. 互斥锁 用于保护临界区,确保同一时间,只有一条线程能够执行 如果代码中只有一个地方需要加锁,大多都使用 self,这样可以避免单独再创建 ...

  7. OC底层原理之Runtime

    本系列主要是看完MJ的OC底层原理课程所写的总结,希望自己能加深对iOS底层的了解. OC的信息机制 OC中的方法调用其实都是转成objc_msgSend函数的调用,给receiver(方法调用者)发 ...

  8. OC基础--OC中的类方法和对象方法

    PS:个人感觉跟C#的静态方法和非静态方法有点类似,仅仅是有点类似.明杰老师说过不要总跟之前学过的语言做比较,但是个人觉得,比较一下可以加深印象吧.重点是自己真的能够区分开! 一.OC中的对象方法 1 ...

  9. oc总结 --oc基础语法相关知识

    m是OC源文件扩展名,入口点也是main函数,第一个OC程序: #import <Foundation/Foundation.h> int main(int argc, const cha ...

最新文章

  1. R语言数据结构之数组
  2. C/C++经典程序训练3---模拟计算器_JAVA
  3. CNCF宣布Envoy项目正式毕业
  4. 用户微服务表结构介绍
  5. RHEL5实现YUM本地源的配置
  6. Chromium内核原理之网络栈HTTP Cache
  7. 如何基于对话框的project基于改变BCG的
  8. 读《scikiit-learn机器学习》支持向量机
  9. 一文搞懂Spring Cloud Zuul
  10. 算法设计与分析——图像的压缩
  11. Firefox中文版与英文版转换
  12. tcp 抓包出现spurious retransmission
  13. MacBook连接打印机-惠普HP LaserJet Pro MFP M427fdn 连接方法
  14. wc与xargs命令
  15. apache(Web服务器)
  16. Android开发中自定义表情并发送出去之经典的发送表情
  17. Excel房贷计算器
  18. 数学脱式计算在线计算机,四年级数学脱式计算练习400题
  19. Android小图标
  20. Boom 3D官方汉化免费下载激活版

热门文章

  1. 栈溢出笔记1.10 基于SEH的栈溢出
  2. Python 链表内取随机数(list取随机数)
  3. Python解决爬虫中文返回乱码问题
  4. 2019-05-27 Java学习日记 day17
  5. jpa-spring -basic
  6. 使用Huploadify上传文件并动态传递参数到后台
  7. [原]openstack-kilo--issue(十八) Error parsing template file: Template format version not found.
  8. Nginx的配置中与流量分发相关的配置规范:
  9. 干货收藏!Python完整代码带你一文看懂抽样
  10. linux下SD卡烧录程序