第6条:理解“属性”这一概念(中)

 属性特质:

  使用属性时还有一个问题要注意,就是其各种特质(attribute)设定也会影响编译器所生成的存取方法。比如下面这个属性就指定了三项特质:

1 @property (nonatomic, readwrite, copy) NSString *testFirstName;

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

  原子性 

   在默认情况下,由编译器所合成的方法会通过锁定机制确保其原子性(atomicity)(在并发编程中,如果某操作具备整体性,也就是说,系统其他部分无法观察到其中间步骤所生成的临时结果,而只能看到操作前与操作后的结果,那么该操作就是“原子的”(atomic),或者说,该操作具备“原子性”(atomicity))。如果属性具备 nonatomic 特质,则不使用同步锁。请注意,尽管没有名为“atomic”的特质(如果某属性不具备 nonatomic 特质,那它就是“原子的”(atomic)),但是仍然可以在属性特质中写明这一点,编译器不会报错。若是自己定义存取方法,那么就应该遵从与属性特质相符的原子性。

  读/写权限

  • 具备 readwrite (读写)特质的属性拥有“获取方法”(getter)与“设置方法”(setter)(也叫获取器、设置器)。
  • 具备 readOnly(只读)特质的属性仅拥有获取方法,只有当该属性由 @synthesize 实现时,编译器才会为其合成获取方法。你可以用此特质把某个属性对外公开为只读属性,然后在“class-continuation 分类” 中将其重新定义为读写属性。

  内存管理语义

  属性用于封装数据,而数据则要有“具体的所有权语义”(concrete ownership semantic)。下面这一组特质仅会影响“设置方法” 。例如,用“设置方法”设定一个新值时,它是应该“保留”(retain)此值呢,还是只将其赋值给底层实例变量就好?编译器在合成存取方法时,要根据此特质来决定所生成的方法,那么就必须同有关属性所具备的特质相符。

  • assign “设置方法”只会执行针对“纯量类型”(scalar type,例如 CGFloat 或 NSInteger 等)的简单赋值操作。
  • strong 此特质表明该属性定义了一种“拥有关系”(owning relationship)。为这种属性设置新值时,设置方法会先保留新值,并释放旧值,然后再将新值设置上去。
  • weak 此特质表明该属性定义了一种“非拥有关系”(nonowning relationship)。为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。此特质同 assign 类似,然而在属性所指的对象遭到摧毁时,属性值也会清空(nil out)。
  • unsafe_unretained 此特质的语义和 assign 相同,但是它适用于“对象类型”(object type),该特质表达一种“非拥有关系”(“不保留”,unretained),当目标对象遭到摧毁时,属性值不会自动清空(“不安全”,unsafe),这一点与 weak 有区别。
  • copy 此特质所表达的所属关系与 strong 类似。然而设置方法并不保留新值,而是将其“拷贝”(copy)。当属性类型为 NSString *  时,经常用此特质来保护其封装性,因为传递给设置方法的新值有可能指向一个NSMutableString 类的实例。这个类是 NSString 的子类,表示一种可以修改其值的字符串,此时若是不拷贝字符串,那么设置完属性之后,字符串的值就可能会在对象不知情的情况下遭人更改。所以,这时就要拷贝一份“不可变”(immutable)的字符串,确保对象中的字符串值不会无意间变动。只要实现属性所用的对象是“可变的”(mutable),就应该在设置新属性值时拷贝一份。

END 

 

posted @ 2017-06-18 01:13  鳄鱼不怕牙医不怕  阅读(187)  评论(0编辑  收藏  举报