属性关键字 assign retain和strong weak

标签(空格分隔): OCTips


OC的内存管理使用了引用计数器,一个对象中的NSUInteger类型变量。MRC下向对象发送消息retain使引用计数器加1,release使引用计数器减1。当引用计数器为0时,对象被释放。此时再使用对象调用方法就会导致崩溃。

MRC内存管理原则:谁retain,谁release

assign

assign一般用于基本数据类型的值;如果非基本类型使用点语法获取值会出现警告Property access result unused - getters should not be used for side effects,此时要使用方法调用[ ]。其作用域为对象赋值操作的代码块区域,类似于一个局部变量。

// 运行于MRC下
@interface ViewController ()
@property (nonatomic, assign) NSMutableArray *array;
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    // 作用域在viewDidLoad方法中
    self.array = [NSMutableArray array];
    [self.array addObject:@2];
    [self.array addObject:@3];
}
- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self.array removeObject:@2];   // 程序崩溃,因为对象已被释放
}
// setter
@property (assign, nonatomic) NSArray *array;
- (void)setArray: (NSArray *)array {
    _array = array;     // 直接赋值给实例变量
}

retain strong

持有特性,使一个对象的引用计数器加一。retain是MRC下的,strong是ARC下的。

// MRC下的方法调用
@interface ViewController ()
@property (nonatomic, retain) NSMutableArray *array;
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    self.array = [NSMutableArray array];    // 创建时retainCount +1
    [self.array addObject:@2];
    [self.array addObject:@3];
}
- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self.array removeObject:@2];
//    [self.array retain];// 要继续使用,就要调用retain方法保持retainCount大于0。此时为2
    [self.array release]; // retainCount +1, retainCount为0,释放对象
    [self.array addObject:@4];      // 再调用方法,程序崩溃。
}
// MRC的setter,ARC 系统自动完成
@property (strong, nonatomic) NSArray *array;
- (void)setArray: (NSArray *)array {
    if (_array != array) {
        [_array release];       // 释放旧值
        _array = [array retain];// 将对象引用计数器加一,再赋值给实例变量
    }
}

weak

MRC下,如果一个对象的retainCount为0,对象会被释放。但他的引用还保留了被释放对象的地址,形成野指针。此时调用方法,编译不会报错,但运行时会崩溃。因此MRC下还需要手动赋值为nil

ARC下,weak属性在retainCount为0时,会自动被赋值为nil。减少了形成野指针的风险。

ARC下如果想要手动释放对象,直接将对象引用赋值为nil即可。

copy

存在一个对象和他的副本,当你希望修改其中一个,但对另一个对象不影响时,使用copy。作为属性关键字时一般用于NSStringblock

相关点:
  深拷贝:源对象引用计数不变,生成一份新的对象(拥有新的内存)
  浅拷贝:源对象引用计数加一,生成一份新的引用,指向源对象。
  值类型引用类型 的使用。
注意:如果对一个可变类型属性使用了copy,会使其变成不可变类型。此时调用可变类型下的方法会出现崩溃。

@property (nonatomic, copy) NSMutableArray *array;
self.array = [NSMutableArray array];
[self.array addObject:@1];  // 崩溃,因为self.array 运行时是NSArray类型,是不能进行增删改操作的。

atomic nonatomic

使用了atomic的属性系统会自动增加同步锁的代码。这样在多线程开发时,避免多个线程同时对属性进行写操作,造成无法预料的属性值。但是会增加性能消耗,同时也不能保证绝对的线程安全。另外,属性默认是atomic的。

当然使用nonatomic则能节省性能。

个人建议就忘掉atomic吧,声明属性都使用nonatomic。多线程安全读写的问题,就在需要写操作时使用NSLock@syncronized等高级方式。

你可能感兴趣的:(属性关键字 assign retain和strong weak)