Objective-C property 属性详解

1,258 阅读4分钟

属性特质:其各种特质(attribute)设定会影响编译器所生成的存取方法。

属性可以拥有的特质分四类:

1.原子性

在默认情况下,由编译器所合成的方法会通过锁定机制保证其原子性。如果属性具备nonatomic特质,则不使用同步锁。

在并发编程中,如果某操作具有整备性,也就是说,系统其他部分无法观察到其中间步骤所生成的临时结果,而只能看到操作前与操作后的结果,那么该操作就是原子的,或者说该操作具备原子性。

atomic 与 nonatomic的区别:具备atomic特质的获取方法会通过锁定机制来确保其操作的原子性,也就是说,如果两个现场读写同一属性,那么不论何时,总能看到有效的属性值。若是不加锁的话(使用nonatomic),那么当其中一个线程正在改写某属性值是,另外一个线程也许会突然闯入,把尚未修改好的属性值读取出来。

但是在iOS开发中,大多数属性都为nonatomic,因为在iOS中使用同步锁的开销较大,会带来性能问题。一般情况下并不要求属性是原子的,因为atomic并不能保证线程安全。例如,一个线程在连续多次读取某属性的过程中有别的线程同时改写该值,那么即便讲属性声明为atomic,也还是会读到不同的属性值。

系统生成的 getter/setter 会保证 get、set 操作的完整性,不受其他线程影响。getter 还是能得到一个完好无损的对象(可以保证数据的完整性),但这个对象在多线程的情况下是不能确定的。也就是说:如果有多个线程同时调用setter的话,不会出现某一个线程执行完setter全部语句之前,另一个线程开始执行setter情况,相当于函数头尾加了锁一样,每次只能有一个线程调用对象的setter方法,所以可以保证数据的完整性。atomic所说的线程安全只是保证了getter和setter存取方法的线程安全,并不能保证整个对象是线程安全的。

2.读/写权限

  • 具备readwrite(读写)特质的属性拥有getter和setter。若该属性由@synthesize实现,则编译器会自动程程这两个方法。
  • 具有readonly(只读)特质的属性仅有有获取方法,只有当该属性由@synthesize实现时,编译器才会其合成获取方法。可以用此特质吧某个属性对外公开为只读属性,然后在“class-continuation分类”中将其重新定义为读写属性。

3.内存管理语义

属性用于封装数据,而数据则要有“具体的所有权语义”。

  • assign “设置方法”只会执行针对“纯量类型(例如CGFloat,NSInteger等)”的简单赋值操作。
  • strong 此特质表明了该属性定义了一种“拥有关系”。设置为strong,指向原来的数据地址,若该数据修改,则用strong修饰的属性会随之变化;strong会对数据地址进行引用计数+1防止原地址被释放。
  • weak 此特殊表明该属性定义了一种“非拥有关系”。设置为weak,指向原来的数据地址,若该数据修改,则用weak修饰的属性会随之变化;但是指向的对象引用计数不变。当属性所指的对象释放时,属性的值会被赋值nil。
  • unsafe_unretained 此特质的语义和assign相同,用于对象类型,表达一种“非拥有关系”,当目标对象被释放时,属性值不会自动清空,仍指向释放的对象,可能造成悬垂指针。
  • copy 开辟新的内存地址来保存同一份数据。被赋值对象和原对象互不影响。

在ARC模式下编程时,指针变量一定要用weak修饰,只有基本数据类型和结构体需要用assgin,例如delegate,一定要用weak修饰。

4.方法名

可通过如下特质指定存取方法的方法名:

@property (nonatomic,getter=isOn) BOOL on;

setter也可以指定设置方法的方法名,这种用法不太常见。