一、Property
- 定义:是Objective-C的一项特性,这一特性可以令编译器自动编写与属性相关的存取方法,并且保存为各种实例变量。
- 本质:属性的本质是实例变量与存取方法的结合。
@property = ivar + getter +setter
- 作用:用于封装对象中的数据
二、Property分类
- 原子性:atomic/nonatomic
- 内存管理(引用计数):assign/strong/copy/weak/unsafe_unretained/retain
- 读写权限:readwrite/readonly
三、atomic与nonatomic
- 原子性定义:并发编程中确保其操作具备整体性,系统其它部分无法观察到中间步骤,只能看到操作前后的结果。
- atomic:原子性的,编译器会通过锁定机制确保setter和getter的完整性
- nonatomic:非原子性的,不保证setter和getter的完整性
- 默认是atomic,atomic也就是线程安全,但atomic的线程安全开销太大,影响性能,即使需要保证线程安全,我们也可以通过自己的代码控制,而不用atomic
四、内存管理
- 关键词
- strong:对对象的强引用,表示指向并拥有该对象,修饰的对象引用计数+1,该对象只要引用计数不为0就不会销毁,强行置空可以销毁它,如果指向了一个空对象会造成一个野指针,一般用来修饰对象类型、字符串类型、集合类型
- copy:建立一个引用计数为1的新对象,使用copy关键字时,将一个对象复制给该属性,该属性不会持有这个对象,而是会创建一个新对象,并将这个对象的值拷贝给它。一般用于修饰字符串和集合类的不可变版
- retain:使用retain修饰变量,会先释放掉旧的对象,然后将旧对象的值赋予输入对象,然后将输入对象的引用计数提升为1。retain较于copy是一个浅复制,复制的只是一个指向相同内容的指针;copy是一个深复刻,完全复制了一个新的对象,此对象引用计数为1,有自己独立的内存地址。推出strong后都用strong,创建block中的修饰属性retain = assign, strong = copy
- weak:对对象的弱引用,表示指向但不拥有该对象,其修饰的对象引用计数不会增加,属性所指的对象遭到摧毁时属性值会清空。ARC环境下一般用于修饰可能会引起循环引用的对象,delegate用weak修饰,xib空间也用weak修饰
- assign:用于非指针变量,一般用于基本数据类型,这些类型不是对象,统一由系统栈进行内存管理
- unsafe_unretained:声明一个弱引用,但销毁时不自动清空,易形成野指针,一般不用
- copy与strong
- strong复制是多个指针指向同一个地址,而copy复制则是每次会在内存中复制一份对象,指针指向不同的地址
- 用strong修饰NSArray时,当数组接受一个可变数组,可变数组若发生变化,被修饰的属性数组也会发生变化,也就是说属性值容易被篡改;若用copy修饰NSMutableArray,当试图修改属性数组里的值,程序会崩溃,因为数组被复制成了一个不可变的版本(接下来会提到)
- assign、weak、unsafe_unretain
- 相同点:都不是强引用
- 不同点:weak引用的OC对象销毁时,指针会自动清空,不再指向销毁的对象,不会产生野指针错误;而unsafe_unretain易产生野指针;assign修饰基本数据类型,内存在栈上由系统自动回收
- copy与mutableCopy
- copy:对于可变对象为深复制(开辟新内存,与原对象指向的不是一个对象了);对于不可变对象是浅复制(不开辟新内存,只是原内存地址加了一个新的指针指向,引用计数+1),返回的对象始终是一个不可变对象
- mutableCopy:始终是深复刻(开辟新内存,与原来对象指向的内存空间不是同一处了),返回的对象始终是一个可变对象
五、readwrite与readonly
- 默认为readwrite
- 一般在.h里面写成readonly,只对外提供读取;在.m的Extension中设置为readwrite可进行读写
六、Property的默认设置
- 基本数据类型:atomic, readwrite, assign
- 对象类型:atomic,readwrite, strong
- 注:规范的关键词属性:原子性、读写权限、内存管理语义、setter/getter