我们在使用@property
这个快捷定义的时候,都没怎么注意系统是怎么实现的,那么我们来看看系统实现的,和我们自己写的setter方法是否一致呢?
Strong
我们来分析一下最简单的strong类型的实现。
1 | @property (nonatomic, strong) NSString *str; |
如果是我们自己写setter方法大概是:
1 | - (void)setStr:(NSString *)str { |
如果是MRC的话,可能是这样的:
1 | - (void)setStr:(NSString *)str { |
当然系统的方法是经过优化的,直接调用的C方法,所以这里不再考虑MRC的写法,直接来对比ARC的结果。
store strong
首先我们来看下objc是如何实现strong的,根据objc的源码可以知道,强引用是通过一个objc_storeStrong
的方法来实现的。其实现入下:
1 | void objc_storeStrong(id *location, id obj) |
这和我们上面MRC的写法类似,只不过是通过C方法来实现了retain和release。
转换为C语言
大家都知道objc的方法其实都是通过send message的方式转换为C语言调用的,所以一个基本的setter方法的最终结果应该是这样的:
1 | void setter(id self, SEL selector, NSString *str); |
具体实现
根据反汇编结果,其中系统默认的实现汇编如下:
1 | sub sp, sp, #0x30 ; 申请栈空间 |
翻译为C语言大概就是这样的:
1 | void setStr(id self, SEL sel, NSString *str) { |
而我们自定义的setter方法
1 | - (void)setStr:(NSString *)str { |
的反汇编结果却比系统的结果多出一些函数调用
1 | sub sp, sp, #0x30 ; =0x30 |
翻译成C语言大概是这样的:
1 | void setStr(id self, SEL sel, NSString *str) { |
可以看到这里多出一个临时变量,而且即使编译优化为-os
,也是同样的结果。这里不清楚为什么会产生一次临时变量,从结果上来看,是不如系统的默认行为的。
Weak
在objc的源码中,weak是通过objc_storeWeak
来实现的,这个方法的实现比较复杂,涉及到了全局的弱引用表,这里就不作介绍了。
同样,我们来对比下系统默认实现的weak类型,和我们重写的setter方法,从结果上来看也是产生了一个strong类型的临时变量。
1 | sub sp, sp, #0x40 ; =0x40 |
1 | sub sp, sp, #0x30 ; =0x30 |