面试题答案
一键面试nonatomic与atomic
- 内存管理:对内存管理无直接影响。
- 线程安全:
- nonatomic:非原子性访问,不保证属性的读写操作是线程安全的。在多线程环境下,可能会出现数据竞争问题。其优势在于性能较高,因为它不涉及线程同步的开销。
- atomic:原子性访问,保证同一时间只有一个线程能访问该属性,提供了线程安全的读/写操作。它通过在访问器方法中添加锁机制来实现线程安全,但这会带来额外的性能开销。
- 适用场景:
- nonatomic:适用于性能要求较高,且所在环境线程安全可通过其他方式保证的场景,比如在单线程环境或者已通过其他锁机制保证线程安全的代码块中。
- atomic:适用于多线程环境下,对数据一致性要求较高,且性能不是首要考虑因素的场景。
strong
- 内存管理:强引用,持有对象的所有权。当一个对象被一个strong修饰的属性所引用时,该对象的引用计数会增加。只有当所有指向该对象的strong引用都被释放后,对象才会被销毁。
- 线程安全:本身不提供线程安全,在多线程环境下,若多个线程同时操作strong属性,可能会导致数据竞争和内存管理问题,需要额外的同步机制。
- 适用场景:通常用于需要保持对象存活,且对象关系为拥有关系的场景。比如视图控制器持有其视图的引用。
weak
- 内存管理:弱引用,不持有对象的所有权,不会增加对象的引用计数。当对象的所有强引用都被释放后,对象被销毁,所有指向该对象的weak引用会自动被设置为nil,避免了野指针问题。
- 线程安全:本身不提供线程安全,在多线程环境下可能存在数据竞争问题。
- 适用场景:适用于解决循环引用问题,比如在视图控制器和其代理之间的关系,代理通常用weak修饰,防止循环引用导致内存泄漏。同时也适用于当你希望对象的生命周期不由自己控制,但又想引用它的场景。
assign
- 内存管理:简单赋值,不涉及引用计数的操作。主要用于基本数据类型(如int、float等),因为基本数据类型不需要通过引用计数来管理内存。对于对象类型,使用assign修饰属性时,不会增加对象的引用计数,当对象被释放后,指向该对象的指针不会自动置为nil,容易产生野指针。
- 线程安全:本身不提供线程安全。
- 适用场景:用于基本数据类型的属性声明。如果非要用于对象类型,仅适用于一些简单场景且能保证对象生命周期长于引用它的对象,否则会有野指针风险。
copy
- 内存管理:创建一个新的对象副本,并持有该副本的强引用。对于不可变对象(如NSString、NSArray等),copy操作通常返回对象本身(浅拷贝),而对于可变对象,会创建一个新的独立副本(深拷贝)。这有助于确保数据的完整性,防止被其他对象意外修改。
- 线程安全:本身不提供线程安全。在多线程环境下,如果多个线程同时操作copy属性,也需要额外的同步机制。
- 适用场景:当你需要确保属性值不会被外部修改时使用。比如,一个视图控制器有一个用于显示文本的NSString属性,为防止外部传入的字符串在其他地方被修改,使用copy修饰该属性。