(一) IOS开发-属性修饰符

140 阅读4分钟

前言

初学OC语言时,在学习属性定义时面对需要定义一个变量属性时,需要用assign、strong、copy还是weak可能会比较容易弄混,即便知道用那个修饰,但对其底层原理也可能不甚了解;本篇主要讲一下自己的相关见解:

内容

1: assign

  • 定义assign 用于基本数据类型(如 intfloatBOOL)以及非对象类型的属性。对于对象类型,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 通常用于不可变对象(如 NSStringNSArray 等)以确保其在属性赋值后不可变。特别是在赋值时,如果传入的是一个可变对象,copy 会生成不可变副本。
  • 原理copy 会将对象的引用计数增加,同时如果对象是可变类型(如 NSMutableString),会创建其不可变副本(NSString)。如果对象已经是不可变类型(如 NSString),则直接使用该对象。
  • 使用场景:常用于字符串和集合类型,确保属性不可变且值不会被外部修改。
  • 示例
@property (nonatomic, copy) NSString *username;
@property (nonatomic, copy) NSArray *items;

4: weak

  • 定义weak 用于对象类型的属性,表示该属性不会增加对象的引用计数,也不会保持对象的生命周期。如果对象被销毁,该属性会自动变为 nil,避免了内存泄漏问题。weak 通常用于避免循环引用,特别是与代理(delegate)相关的场景。
  • 原理weak 保持对对象的弱引用,不会影响对象的引用计数。因此,如果没有其他强引用持有对象,当对象销毁时,weak 引用会自动被置为 nilweak 属性不能用于 nil 值的对象,因此要小心使用。
  • 使用场景:用于防止循环引用,特别是在代理和委托模式中,以及当对象需要在其生命周期内可被销毁时。
  • 示例
@property (nonatomic, weak) id<SomeDelegate> delegate;
@property (nonatomic, weak) UIView *view;

总结

  • assign:适用于基本数据类型(如 intfloat 等)和需要手动管理内存的对象。它不会保持对象的强引用,因此容易造成野指针问题。
  • strong:适用于对象类型,表示强引用,会保持对象直到属性被赋值为 nil 或其他对象。通常用于需要管理内存的情况。
  • copy:适用于对象类型,确保对对象进行复制,避免外部修改对象的内容。常用于字符串(NSString)和集合类型(如 NSArray)。
  • weak:适用于对象类型,保持弱引用,不会增加对象的引用计数,用于避免循环引用(如代理模式)。当对象被销毁时,weak 会自动设置为 nil