前言
初学OC语言时,在学习属性定义时面对需要定义一个变量属性时,需要用assign、strong、copy还是weak可能会比较容易弄混,即便知道用那个修饰,但对其底层原理也可能不甚了解;本篇主要讲一下自己的相关见解:
内容
1: assign
- 定义:
assign用于基本数据类型(如int、float、BOOL)以及非对象类型的属性。对于对象类型,assign不会进行内存管理,意味着它不会持有对象,只是简单地赋值。 - 原理:
assign直接将值赋给属性,而不会保持对对象的强引用,也不会进行对象引用计数管理。对于基本数据类型,它只是直接赋值。对于对象类型,assign不会保留对象,因此可能会导致对象在外部释放时属性指向野指针(dangling pointer)的问题。 - 使用场景:一般用于基础数据类型,或者不需要内存管理的对象属性。
- 示例:
@property (nonatomic, assign) NSInteger count; // 用于整数
@property (nonatomic, assign) BOOL isValid; // 用于布尔值
2: strong
- 定义:
strong用于对象类型的属性,表示该属性会持有对象的强引用,也就是增加该对象的引用计数。当属性值被替换时,原对象的引用计数会减少,新的对象会被强引用。 - 原理:
strong会确保对象在属性持有期间不会被释放,即使外部对该对象的引用计数变为零。通常用于所有需要保持对象生命周期的情况。 - 使用场景:一般用于对象类型属性,确保对象在其生命周期内不会被销毁,如UI组件和可变数组等可变对象等。
- 示例:
@property (nonatomic, strong) Label *nameLabel;
@property (nonatomic, strong) NSMultableArray *items;
3: copy
- 定义:
copy用于对象类型的属性,表示该属性会持有对象的副本(copy),而不是直接持有原始对象。copy通常用于不可变对象(如NSString、NSArray等)以确保其在属性赋值后不可变。特别是在赋值时,如果传入的是一个可变对象,copy会生成不可变副本。 - 原理:
copy会将对象的引用计数增加,同时如果对象是可变类型(如NSMutableString),会创建其不可变副本(NSString)。如果对象已经是不可变类型(如NSString),则直接使用该对象。 - 使用场景:常用于字符串和集合类型,确保属性不可变且值不会被外部修改。
- 示例:
@property (nonatomic, copy) NSString *username;
@property (nonatomic, copy) NSArray *items;
4: weak
- 定义:
weak用于对象类型的属性,表示该属性不会增加对象的引用计数,也不会保持对象的生命周期。如果对象被销毁,该属性会自动变为nil,避免了内存泄漏问题。weak通常用于避免循环引用,特别是与代理(delegate)相关的场景。 - 原理:
weak保持对对象的弱引用,不会影响对象的引用计数。因此,如果没有其他强引用持有对象,当对象销毁时,weak引用会自动被置为nil。weak属性不能用于nil值的对象,因此要小心使用。 - 使用场景:用于防止循环引用,特别是在代理和委托模式中,以及当对象需要在其生命周期内可被销毁时。
- 示例:
@property (nonatomic, weak) id<SomeDelegate> delegate;
@property (nonatomic, weak) UIView *view;
总结
assign:适用于基本数据类型(如int、float等)和需要手动管理内存的对象。它不会保持对象的强引用,因此容易造成野指针问题。strong:适用于对象类型,表示强引用,会保持对象直到属性被赋值为nil或其他对象。通常用于需要管理内存的情况。copy:适用于对象类型,确保对对象进行复制,避免外部修改对象的内容。常用于字符串(NSString)和集合类型(如NSArray)。weak:适用于对象类型,保持弱引用,不会增加对象的引用计数,用于避免循环引用(如代理模式)。当对象被销毁时,weak会自动设置为nil。