5–类的底层探索之属性

成员变量 vs Property

Clang

首先先介绍一下clang, clang是一个由Apple主导编写,基于LLVMC/C++/OC的轻量级编译器
主要是用于底层编译,将一些文件输出成c++文件,例如main.m 输出成main.cpp,其目的是为了更好的观察底层的一些结构及实现的逻辑,方便理解底层原理.

探索

image.png
成员变量和属性的区别
基本数据类型(int float NSString*) 称为成员变量。
imp : 方法的具体实现,函数的指针。
cmd : 方法编号。
SEL : 方法的名字。

首先我们探索下property 和 成员变量在底层的结构是什么样的

clang -rewrite-objc main.m -o main.cpp 通过clangmain.m输出为main.cpp

image.png
image.png
image.png
从上述源码中我们可以看到所有的property都有生成对应的set/get方法,但是
为什么hobbyset方法是通过内存偏移的方式去赋值,而yyyName是通过objc_setProperty实现的呢?
那我们就去查看LLVM的源码,研究下为什么setYyyName会调用objc_setProperty, 下图是LLVM的源码创建setProperty的函数
image.png
我们再反推回去找什么地方调用的GetPropertySetFunction

image.png
image.png
由上图可知,发现是通过switch strategy.getKind()来确定是否需要setProperty
image.png
image.png
终于在一番查找之后发现当是copyproperty的时候,strategy的赋值为GetSetProperty. 由此解释了为什么copyset方法是需要调用setProperty的原因.

探索

什么时候会生成objc_getProperty

编码

image.png
通过看源码,会看到一些比较奇怪的符号,比如上图中,这些符号就是编码
可以通过@encode()函数得到所有类型的encode符号

char *buf1 = @encode(int **);
char *buf2 = @encode(struct key);
char *buf3 = @encode(Rectangle);
复制代码

API

通过#import <objc/runtime.h>中的API获取类方法,实例方法

class_getInstanceMethod
class_getClassMethod
class_getMethodImplementation
复制代码

image.png

image.png

class_getMethodImplementation探索,为什么我们有时候并没有实现一个方法,但是当调用class_getMethodImplementation返回却不为空呢?因为会发挥一个默认值。
image.png

扩展

image.png

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