@property
OC中,通过以下代码声明一个属性:
@property(描述1 , 描述2 , 描述3)(class *) varName
其中三个描述词如下(可以不填,有默认值):
描述1:nonatomic<-->atomic (默认值atomic)
atomic
保证了属性的原子性,其原理是在生成getter和setter方法时,使用互斥锁@synchronized(self)
来保证对属性读/写的安全性(可以理解成会按调用的顺序串行执行),但其并 不能保证 线程的安全性,如果使用多线程同时修改其属性值,因为不能线程的执行顺序,所以执行的结果也不能确定。
nonatomic
不保证属性的原子性,也就不会加上同步锁,所以效率上相比atomic
要高,理论上如果没有特殊要求(不存在并发问题)的话, iOS 用 nonatomic 比较好。
描述2:readwrite<-->readonly (默认值readwrite)
readwrite
可读写,外部可以正常调用getter和setter方法。
readonly
只读,外部只能调用getter方法,不能调用setter方法。
描述3:strong/copy/weak/assign (默认值assign)
在自动生成setter函数的时候,编译器需要识别这个描述词来生成对应的setter函数。
strong
: 对retain的ARC实现,对属性进行强引用。
copy
: 生成setter函数时会使用copy方法(一般来说,对于不可变对象进行浅拷贝,可变对象进行深拷贝)
weak
: 对属性进行弱引用,不会持有对象。当所有指向属性的strong类型指针都移除时,weak指针也会被移除。
assign
: assign是指针赋值,不对引用计数操作,使用之后如果没有置为nil,可能就会产生野指针。通常用assign修饰基础数据类型。
如果自己实现了getter和setter方法,则三个描述词只起到提示作用,而没有实际作用
@synthesize
使用@synthesize 只有一个目的——给实例变量起个别名
iOS 6 之后 LLVM 编译器引入property autosynthesis,即属性自动合成。换句话说,就是编译器会为每个 @property 添加 @synthesize ,如以下形式:
@synthesize propertyName = _propertyName;
- 当使用@synthesize 给属性添加别名后,将会覆盖自动合成的别名,只能使用新的别名。
- 如果在protocol中声明了属性(其实只有getter和setter方法,并没有属性实例),那么在使用它之前,需要使用@synthesize来合成属性实例。
@dynamic
@dynamic告诉编译器,属性的setter与getter方法由用户自己实现,不自动生成。
- 如果使用了@dynamic声明了属性,而没有实现setter/getter方法,虽然在编译时能够通过,但会在实际运行时由于缺少方法而崩溃(动态绑定)。
- 主要使用在CoreData的实现NSManagedObject子类时使用,由Core Data框架在程序运行的时动态生成子类属性。
网友评论