文章为原创,转载请注明出处
对象(Object) & 消息传递(Messaging)
- 对象:基本构造单元,开发者可以用来存储并传递消息
- 消息传递:在对象间传递数据并执行任务的过程叫“消息传递”
属性
-
定义: 属性用于封装对象的数据,Objective-C对象将需要的数据保存为各种实例变量(ivar),实例变量一般用存取方法获得(getter & setter),通过点语法访问属性。可总结为 property = ivar + getter + setter
-
属性解决的问题:定义实例变量,对象布局在编译期固定,碰到实例变量会转为“偏移量”,表示变量和对象起始内存地址的距离,编译期的偏移量,在使用新的定义和旧定义链接时会出错。把实例变量当成存储偏移量的特殊变量交给类保管,类定义变了,偏移量也就变了,类定义变了存储也就变了,这就是稳固的 “程序二进制接口ABI”,这样就可以在"class-continuation"或实现文件中定义实例变量了
@Property, @synthesize和@dynamic
- @property:使用属性封装对象里的数据,编译期自动生成存取方法,使用"点语法"访问属性,编辑器里看不到这些“合成方法”,这一过程称为"autoSynthesize"
- @synthesize:用来指定合成的实例变量名(ivar),推荐使用"_name"语法
- @dynamic:不自动创建实例变量,不生成存取方法,编译器访问代码时不会报错,因为在运行时去找这些代码
属性特质
-
nonatomic:非原子的,iOS开发一般使用,使用非原子的属性不具有同步锁
-
atomic:原子的,没有这个定义,属性默认是原子的(一个属性不是非原子的,那就是原子的),不能保证线程安全,有额外开销,在MacOS开发不会太影响性能
-
readwrite:读写 readonly: 只读
-
内存管理语义:只会影响设置方法,自己编写时必须使用属性相关的特性
- strong:拥有关系,设置时保留新值释放旧值
- weak:非拥有关系,设置时不保留新值不释放旧值,属性指向的对象销毁时,属性也清空
- assign:和weak一样,但只用于纯量类型(CGFloat)
- unsafe_retained:语义与assign相同,适用于“对象类型”,对象被摧毁时,属性值不会清空
5.copy:语义与strong相同,设置时不保留旧值,复制新值,一般有可变类型的对象都使用copy,用来保护其封装性
在对象内部直接访问实例变量
内部访问&外部访问
- 内部访问:在读取实例变量时直接访问(ivar),在设置时用设置方法
- 外部访问:通过属性来访问
内部访问访问"存取方法"和使用“实例变量”的区别
- 不经过Objective-C方法派发,直接访问实例变量更快,编译器直接访问实例变量的地址(*ivar_list)
- 直接访问绕过内存管理语义,不调用设置方法,在ARC下访问Copy不会将其拷贝,只会保留新值释放旧值
- 直接访问不会触发KVO
- 通过属性访问有利于排查错误,可以在存取方法里添加断点
在初始化方法中直接访问实例变量
因为子类有可能覆写属性的设置方法,所以要用实例变量来访问,要初始化的属性要是在超类里,就只能用设置方法了
惰性初始化
惰性初始化通过存取方法访问