第2章 对象、消息、运行期
对象
是面向对象语言编程的基本构造单元,通过其存储并传递数据;消息传递
是对象之间传递数据并执行任务的过程。
第6条:理解“属性”这一概念
属性(Property)
,用于封装对象中的数据。Objective-C对象把其所需要的数据保存为各种实例变量。实例变量通过存取方法(access method)
访问。获取方法(getter)
读取变量值,设置方法(setter)
写入变量值。
属性
编译器自动生成存取方法,用以访问给定类型中具有给定名称的变量点语法
编译器自动转换为存取方法的调用,二者没有差别- 使用属性,编译器会1.自动编写访问属性所需的方法(自动合成)2.自动向类中添加适当类型的实例变量,以属性名前加下划线作为实例变量的名字
- 存取方法,除了自己实现,否则编译器会实现未自己实现的方法
@dynamic
关键字告诉编译器,不要自动创建实现属性所用的实例变量,与存取方法
属性特质
原子性
nonatomic/atomic
读/写权限
readwrite
(读写)特质的属性拥有“获取方法”与“设置方法”,由@synthesize实现,自动生成两个方法readonly
(只读)特质的属性仅拥有“获取方法”,只有@synthesize实现,才会合成获取方法
内存管理语义
仅影响“设置方法”,保留值?只赋值给实例变量?根据此特质决定生成的方法代码
assign
“设置方法”只会执行针对“纯量类型”(如:CGFLoat、NSInteger等)简单赋值strong
定义”拥有关系”,为属性设置新值时,设置方法会先保留新值,并释放旧值,在设置上新值weak
定义“非拥有关系”,设置新值,不保留新值,也不释放旧值。同assign类似,所指对象销毁时,会被清空unsafe_unretained
语义与assign相同,适用于“对象类型”,表达“非拥有关系”,目标对象被摧毁,属性值不自动清空copy
有strong类似,不保留新值,将其拷贝。只要实现属性所用的对象是“可变的(mutable)”,应该设置新属性值时拷贝。- 方法名
- getter=
指定“获取方法”的方法名 - setter=
指定“设置方法”的方法名
要点
- 可以用
@property
语法定义对象中所封装的数据 - 通过“特质”指定存储数据所需的正确语义
- 在设置属性所对应的实例变量时,一定要遵从该属性所声明的语义
- 开发iOS时应该使用
nonatomic
属性,因为atomic
严重影响性能
第7条:在对象内部尽量直接访问实例变量
- 在对象之外总是应该通过属性访问实例变量
- 在对象之内建议读取实例变量时采用直接访问的形式,设置实例变量时通过属性来做
- 直接访问实例变量速度快(直接访问保存对象实例变量的内存);不调用“设置方法”,绕过了“内存管理语义”;不会触发“KVO”通知;使用属性访问有助于排查与之相关的错误
- 折中方案:写入实例变量使用“设置方法”来做,读取实例变量,直接访问。
- 初始化方法中设置属性值应该直接访问实例变量,以防被子类“覆写”设置方法
惰性初始化
必须通过“获取方法”来访问属性,否则,实例变量永远不会初始化
要点
- 在对象内部读取数据时,应该直接通过实例变量来读,而写入数据时,应该通过属性来写
- 在初始化方法及
dealloc
方法中,应该直接通过实例变量来读写数据 - 使用惰性初始化技术配置数据,需要通过属性来读取数据