Effective Objective-C 2.0 — 第二章 对象、消息、运行期 - 第六条:理解“属性”这一概念

  • 开发者通过对象来 存储并传递数据。
  • 在对象之间传递数据并执行任务的过程就叫做“消息传递”。

这两条特性的工作原理?

Objective-C运行期环境(Objective-C runtime) ,提供了使得对象之间能够传递消息的重要函数,并且包含创建类实例所用的全部逻辑。

@interface EOCPerson : NSObject {
@public 
   //NSString *_dateOfBrith;  
    NSString *_firstName;
    NSString *_lastName;
@private
    NSString *_aomeInternalData;
}
@end

这种写法问题,对象布局在 编译器(compile time)就已经固定了。只要碰到访问——firstName变量的代码,编译器就把其替换为“偏移量”(offset),这个偏移量是“硬编码”(hardcode),表示带变量距离存放对象的内存区域的起始地址有多远。

但是又加了一个实例变量就会出错,原来表示_firstName的偏移量现在却指向 _dateOfBirth了。

Objective-C的应对做法是,把实例变量当作一种存储偏移量所用的“特殊变量”,交由“类对象(class object)保管。偏移量会在运行期查找,如果类的定义变了,那么存储的偏移量也就变了。这样甚至可以在运行期向类中新增实例变了,这就是稳固的”应用程序二进制接口“ABI。有了ABI,就可以在class-continuation分类或 实现文件中定义实例变量了

另一种解决办法:

1,通过@property语法来定义对象中所封装的数据

属性优势:如果使用了属性,编译器就会自动编写访问这些属性所的方法,此过程叫做”自动合成“(autosynthesis),此过程在编译器执行

@dynamic :告诉编译器:不要自动创建实现属性所用的实例变了,也不要为其创建存取方法。

属性特质 :

原子性

(atomicity) ,系统其他部分无法观察到其中间步骤所生成的临时结果,而只能看到操作前与操作后的结果,该操作就是(atomic)

读写权限

内存管理语义

(concrete ownership semantic) 具体的所有权语义

assign :”设置方法“只会执行针对”纯量类型“(scalar type, 例如CGFloat 或 NSInteger等)的简单赋值操作。

strong :表明该属性定义了一种”拥有关系“(owning relationship)为这种属性设置新值时,设置方法会先保留新值,并释放旧值,然后再将新值设置上去。

weak:表明该属性定义了一种”非拥有关系“(nonowning relationship)为这种属性设置新值时,设置方法会既不保留新值,也不释放旧值,与assign相似,再属性所致的对象遭到摧毁时,属性值也会清空(nil out)

unsafe_unretained : 此特质的语义和assign系那个痛,但它适用于”对象类型“(object type),该特质表达一种”非拥有关系"("不保留",unretained), 当目标对象遭到摧毁时,属性值不会自动清空(“不安全”,unsafe),这一点与weak有区别。

copy:与strong类似。但是设置方法并不保留新值,而是“拷贝”。当属性为NSString 时经常用来保护其封装性,因为有可能传递给设置方法的新值指向一个NSMutableString类的实例,可以修改其值的字符串,若不用copy那么设置完属性后,可能在对象不知情的情况下遭人更改

方法名:

getter=<name> 指定获取方法的方法名。如果属性是Boolean型,而你想加前缀“is",就可以用这个方法来指定。

如表示”开关“(switch)是否打开的属性就是 这样定义的:

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

atomic 与 nonatomic 的区别是:

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

使用同步锁的开销较大,性能不好。一般使用nonatomic属性。