成员变量 vs Property
Clang
首先先介绍一下clang, clang
是一个由Apple
主导编写,基于LLVM
的C/C++/OC
的轻量级编译器
主要是用于底层编译,将一些文件输出成c++
文件,例如main.m
输出成main.cpp
,其目的是为了更好的观察底层的一些结构及实现的逻辑,方便理解底层原理.
探索
成员变量和属性的区别
基本数据类型(int float NSString*)
称为成员变量。
imp
: 方法的具体实现,函数的指针。
cmd
: 方法编号。
SEL
: 方法的名字。
首先我们探索下property 和 成员变量在底层的结构是什么样的
clang -rewrite-objc main.m -o main.cpp
通过clang
将main.m
输出为main.cpp
从上述源码中我们可以看到所有的property
都有生成对应的set/get
方法,但是
为什么hobby
的set
方法是通过内存偏移的方式去赋值,而yyyName
是通过objc_setProperty
实现的呢?
那我们就去查看LLVM的源码,研究下为什么setYyyName
会调用objc_setProperty
, 下图是LLVM的源码创建setProperty
的函数
我们再反推回去找什么地方调用的GetPropertySetFunction
由上图可知,发现是通过switch strategy.getKind()
来确定是否需要setProperty
终于在一番查找之后发现当是copy
的property
的时候,strategy
的赋值为GetSetProperty
. 由此解释了为什么copy
的set
方法是需要调用setProperty
的原因.
探索
什么时候会生成objc_getProperty
?
编码
通过看源码,会看到一些比较奇怪的符号,比如上图中,这些符号就是编码
可以通过@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
复制代码
class_getMethodImplementation
探索,为什么我们有时候并没有实现一个方法,但是当调用class_getMethodImplementation
返回却不为空呢?因为会发挥一个默认值。