OC底层原理5之copy的特殊,runtime的几个方法

本章内容

  1. WWDC2020针对runtime进行的三项优化
  2. 类的加载方式是什么方式(懒加载)
  3. 实例变量,属性,成员变量区别
  4. copy与其他修饰符是哪的地方不同
  5. objc_setProperty方法在底层是什么情况下调用的
  6. 方法的编码
  7. runtime的几个方法

类的加载方式

这次只进行简单的验证,验证类的加载方式是懒加载模式,至于为什么以及原理是什么先不做深究。例如:继承关系:Teacher -> Person -> NSObject。

注意我们的验证流程实在objc源码工程进行验证,脱离源码环境的情况需要自行去取样,也就是把源码复制一份到工程

流程:

Person类指针地址 —-> 平移0x20得到bits —-> 调用class_rw_t* data() 获取class_rw_t* —-> 输出class_rw_t结构查看 —–> 调用Teacher.class方法 —->输出class_rw_t结构查看

验证:

1、进行LLDB调试执行代码 Person *p = [Person alloc]就发现在类Person的结构中,其第四个成员是bits,它的本质是class_data_bits_t 的结构体指针,通过bits我们可以获取class_rw_t结构体指针,如有疑问请看类的本质然后查看到firstSubclass为空。

补充:nextSiblingClass代表内存中与Person类相邻的类是NSUUID

image.png

2、执行[Teacher class]然后查看Person的class_rw_t,发现firstSubclass显示为Teacher

image.png

实例变量,属性,成员变量

1、属性:为ivar + setter + getter,也就是成员变量 + 系统为属性自动生成的setter和getter方法

2、成员变量:只是单纯的ivar,例如:int, char, double, float, string, bool等类型。在底层编译是常规数据类型的

3、实例变量:特殊的成员变量,例如NSObject类型,可以认为在底层编译是结构体的

验证:用clang进行验证

例如:我们创建的Person类

image.png

转为cpp文件以后查看

image.png

修饰符copy的特殊之处

我们一提起copy就说它是拷贝,如果对象要实现深拷贝就要实现NSMutableCopying协议,如果要实现浅拷贝就要实现NSCopying协议,然后深拷贝拷贝的是内容,浅拷贝拷贝的是指针,也就是指针引用。附深浅拷贝

1、查看Person类

分别定义了5种不同的属性
image.png

2、查看经过clang转换的C++源码

1、看了对象Person的结构
image.png

2、看属性nonatomic_strong_name的setter和getter方法,得到strong修饰的是属性是isa+内存平移得到。
image.png

3、看属性nonatomic_copy_name的setter和getter方法,得到copy修饰的是属性,getter方法是isa+内存平移,setter是调用了objc_setProperty方法
image.png

4、看属性nonatomic_name的setter和getter方法,跟strong一样是isa+内存平移得到
image.png

5、看属性atomic_copy_name的setter和getter方法,得到getter方法是调用了objc_getProperty方法,setter方法是调用了objc_setProperty方法
image.png

6、看属性atomic_name的setter和getter方法,跟strong一样是isa+内存平移得到
image.png

3、疑问与总结

疑问:为什么属性nonatomic_copy_name与atomic_copy_name同其他属性不一样呢,为什么会调用objc_setProperty方法呢,又为什么atomic和copy一起修饰的时候又会调用objc_getProperty方法呢

总结:如果用copy修饰的属性setter方法一定会调用objc_setProperty,而更特殊但不经常用的修饰方式(atomic和copy)会调用objc_getProperty。这是因为在苹果编译框架LLVM层的时候就根据这两个属性进行了判断。在这里只演示LLVM结果
image.png
image.png
image.png

4、objc_setProperty的objc源码是怎么回事

其实不止是objc_setProperty还有objc_setProperty_atomicobjc_setProperty_atomicobjc_setProperty_nonatomicobjc_setProperty_atomic_copyobjc_setProperty_nonatomic_copy等6个方法都指向了最终一个方法—–> reallySetProperty

注意:请看atomic的条件判断,得知在底层的原子性就是加了个锁而已,为了读取安全,但是读取安全并不代表线程安全。有个面试题会经常被问到atomic真的线程安全吗?答案是不一定的,例如:异步线程A进行赋值,线程B进行读取,里面各自的操作循环很多次。
image.png

5、objc_getProperty的objc源码是怎么回事

image.png

方法的编码

在LLDB进行查看方法的输出的时候,我们经常看到一些编码例如:

image.png
image.png

  1. v 代表返回类型 void
  2. 16 代表方法参数总和需要的字节大小 16字节
  3. @ 代表第一个参数类型是id类型
  4. 0 代表第一个参数从字节0号位开始
  5. : 代表第二个参数类型 SEL
  6. 8 代表第二个参数从字节8号位开始

总结:每一个字符都代表了不同的编码。编码对照表进行查看。

runtime的几个方法

以下内容是我自己的笔记内复制过来的,将就着看
image.png

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享