以前一直以为OC中的set方法在底层统一调用了objc_setProperty方法,后来在研究OC生成的C++代码过程中,发现有的set方法使用了指针偏移的方式直接访问实例变量,有的却是使用objc_setProperty
@interface SetterTest : NSObject
@property (nonatomic, strong) NSString *a;
@property (nonatomic, copy) NSString *b;
@property (atomic, strong) NSString *c;
@property (nonatomic, strong) NSString *d;
@end
@implementation SetterTest
@end
观察上面的代码发现,确实是使用了两种方式。由于代码生成的不同,所以猜测是编译器来控制的,在
LLVM源码中搜索objc_setProperty发现了以下代码:
通过名字就可以发现,这是用来生成
set方法的,代码中通过判断PropertyImplStrategy strategy来生成不同的set方法,PropertyImplStrategy实现如下:
那么接下去只需要知道
PropertyImplStrategy是如何初始化的,就能知道编译器是怎么区分属性的。
关键代码 1:如果是Copy 那么必然使用SetProperty,至于Get 则根据是否是原子性判断。
// If we have a copy property, we always have to use setProperty.
// If the property is atomic we need to use getProperty, but in
// the nonatomic case we can just use expression.
关键代码 2:如果不是Copy,则根据原子性来判断,当使用原子性时,则会使用SetProperty