assign
- 特点:简单赋值,不改变引用计数。适用于基本数据类型(如
int
、float
、char
等),对于对象类型,当对象释放后,指针不会自动置为 nil
,可能产生悬空指针。
- 适用场景:基本数据类型的属性声明。
- 示例:
@property (nonatomic, assign) int age;
retain
- 特点:对对象进行引用计数加1操作。当对象的引用计数变为0时,对象被释放。
- 适用场景:在MRC(手动引用计数)时代,用于对需要保持所有权的对象进行属性声明。
- 示例:
@property (nonatomic, retain) NSString *name;
copy
- 特点:创建一个新的对象副本,新对象的引用计数为1。对于不可变对象,通常返回自身(浅拷贝);对于可变对象,返回一个新的对象(深拷贝)。
- 适用场景:当需要确保属性值不被外部修改时,如
NSString
、NSArray
、NSDictionary
等。防止外部传入可变对象后,对象内容被修改影响到本类数据。
- 示例:
@property (nonatomic, copy) NSString *text;
strong
- 特点:ARC(自动引用计数)下的强引用,等同于MRC中的
retain
,会增加对象的引用计数。当强引用指向的对象没有其他强引用时,对象会被释放。
- 适用场景:一般情况下,需要持有对象所有权时使用。
- 示例:
@property (nonatomic, strong) NSObject *object;
weak
- 特点:弱引用,不会增加对象的引用计数。当对象被释放时,指向该对象的所有弱引用会自动被设置为
nil
,避免悬空指针。
- 适用场景:用于解决循环引用问题,如视图控制器之间的父子关系,或者避免持有对象而导致对象无法释放。
- 示例:
@property (nonatomic, weak) UIViewController *parentViewController;
避免内存泄漏和悬空指针
- 内存泄漏:在ARC下,避免循环引用可解决大部分内存泄漏问题。例如在两个对象相互强引用时,可将其中一个改为弱引用。
@interface ClassA;
@interface ClassB {
@property (nonatomic, strong) ClassA *a;
}
@end
@interface ClassA {
@property (nonatomic, weak) ClassB *b; // 使用weak避免循环引用
}
@end
- 悬空指针:使用
weak
修饰符,当对象释放时,指向该对象的 weak
指针会自动置为 nil
,防止访问已释放对象导致的悬空指针问题。
__weak NSObject *weakObject;
{
NSObject *strongObject = [[NSObject alloc] init];
weakObject = strongObject;
} // strongObject出作用域被释放,weakObject自动置为nil