引言:
说到修饰符,脑海中第一反应
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, copy) NSString *name;
这里有nonatomic,assign,copy等。我们常用的还有strong,weak等。所以这篇想先聊聊这几个修饰符。
nonatomic与atomic
atomic:原子性操作,对属性的读写是线程安全的,系统会生成额外的代码保证多线程下属性读写的完整性。但这并不意味着它是绝对线程安全的,只是保证在读取和写入属性值的时候不会被其他线程干扰。举个例子:people有两个属性姓和名。假设一开始这个人叫张三,我们给他改名李四。如果是多线程读写,可能会读到张四这个不存在的名字。这两个属性操作是原子的,但是这个对象不是原子的。因为只是锁getter,setter,如果对象是可变数组,那么也不保证数组内元素的getter,setter。 另一方面,加锁会带来一定的性能开销,在对性能要求较高且不是多线程竞争激烈的情况下,通常会使用nonatomic。nonatomic:非原子性操作,不保证多线程下的安全读写,是默认的属性修饰。通常在绝大多数情况下使用nonatomic,因为它的性能更好。
strong与weak
strong:强引用,用于对象类型的属性。拥有该对象,只要有一个强引用指向一个对象,这个对象就不会被释放。通常用于普通的对象属性,比如UIViewController中的视图属性等。weak:弱引用,不会增加对象的引用计数。当所指向的对象被释放时,弱引用会自动被置为 nil,避免了悬空指针的问题。通常用于避免循环引用的情况,比如在delegate属性中。
- 实现机制上,Objective-C 运行时系统会维护一个弱引用表。当一个对象被弱引用指向时,会在这个表中记录弱引用和被引用对象的关系。
- 当对象被释放时,运行时系统会遍历弱引用表,将所有指向该对象的弱引用置为
nil。
顺便引申一下 @weakif/@strongif:与属性修饰中的weak和strong类似,用于在特定场景下管理对象的引用。比如在 block 中避免循环引用。
strong与copy
copy:一般用于不可变对象(如NSString等)的属性,会在赋值时创建一个副本,避免原始对象被修改影响到属性值。对于可变对象使用copy修饰,会将其转换为不可变对象的副本。 这里提一嘴,一般用strong修饰object,而用copy修饰NSString。因为一般我们引用对象的时候,是希望用同一个对象。比如张三这个人。而引用NSString的时候,由于oc里面,mutable是子类,如果用了strong修饰NSString,可能本质是NSMutableString,后面修改的时候,改一处,就会改动到很多地方,引起不必要的问题。一般用string也只是想要初始的那个值,而不希望被其他地方改动。不过,如果有特殊需求,可以自行决定用哪个修饰。
retain
用的比较少。现在都用arc了。之前手动管理内存的时候,如果一个对象是retain,那么赋值的时候,会自动给新的对象增加引用计数。对应的,使用release进行释放。
一些其他的比如unknown,unsafe_unretained且等日后有机会再聊