原文
@property是一条编译器指令,用于编译器为实例变量自动生成setter
和getter
方法。
@property与@synthesize
在Xcode 4.0版本之前,确实是不写@synthesize
不行,后来版本中的LLVM优化了这个语法,只写@property
不写@synthesize
也可以自动合成setter
和getter
方法。自动合成的属性所对应的实例变量名就是属性名在前面加“_”,如果我们不想使用这个实例变量名,就可以使用@synthesize来指定实例变量名字。如@synthesize content = textContent;
。但实例变量中使用下划线作为开头,已经成了广大开发者约定俗成的习惯,所以如果没有特殊需求,建议还是遵循规范,不需要写@synthesize
,直接声明属性@property
。
@property与KVO
KVO全称是Key-Value Observing,是Objective-C语言中的一种核心机制,我们一般翻译为键值观察。至于KVO的实现方式,相信很多人也知道,就是继承该类并重写setter方法,当调用setter方法的时候,通知监听器回调。前文说到了,@property
可以自动合成setter,所以这里正是它和KVO之间千丝万缕的关系。
我们访问变量有几种方式,遵循Objective-C调用方法的方式访问[self variableName]
是一种,self.variableName
语法糖是一种,直接访问实例变量_variableName
也是一种,这三种方式有什么区别呢?
-
方法调用
[self variableName]
如前文所讲,这种方式正是使用了getter方法,通过getter返回值的来访问到实例变量的值,遵循良好的封装性。
-
点语法糖
self.variableName
正如它的名字一样,这种方式其实只是一种语法糖,其背后根本上还是调用getter方法。
-
直接访问实例变量
_variableName
不经过取设方法,直接访问实例变量所在内存位置。优点在于不经过方法调用,速度更快。
同样看一下设值的方式呢,也有如下三种:
-
方法调用
[self setVariableName]
使用setter来设值。
-
点语法糖
self.variableName = @"talisk"
语法糖,背后同样是setter方法。
-
直接访问实例变量
_variableName = @"talisk"
不经过设值方法,将新值赋给实例变量所在内存区域。优点还是不经过方法调用,速度更快。然而问题也很明显,用这种方式改变值KVO失效,跳过了setter中内存管理的特质。比如你给某个字符串赋了mutable可变字符串,若该属性内存管理特质为copy,此时通过setter设值会深拷贝一份不可变字符串,但直接访问该实例变量不通过setter会导致没有拷贝出一份不可变字符串。
对于这样的问题,我们大概可以总结出最佳使用姿势:
在需要设值的地方,我们通过setter设值方法设值;当需要取值的时候,我们采用直接访问实例变量的方式。
另外要注意,初始化方法中,没有特殊需要,应该尽量直接访问实例变量。
网友评论