陈斌彬的技术博客

Stay foolish,stay hungry

iOS-@property的参数

在OC的内存管理中,如果忘记释放OC对象,很有可能就造成内存泄露。为了避免忘记释放内存,我们通常在setter方法中释放类属性中的OC对象,这也使得代码过于麻烦。好在@property的参数解决了这个问题。

正文:

一. 首先,@property都有哪些常用参数

除了这些,还有getter和setter等,将在下面做讲解。

二. 详细讲解

1. readwrite / readonly

系统默认值为:readwrite。

@property (readwrite) int age;

等价于:

@property int age;

等价于:

- (void) setAge : int newAge {

   _age = newAge;
}

- (int) getAge {

   return _age;
}

如果设置属性只读:

@property (readonly) int age;

等价于:

- (int) getAge {

   return _age;
}

2. assign / retain / copy

这对参数主要用于OC对象释放的时候。assign是在setter时,直接赋值,没有额外操作,而retain则需要先释放旧的对象,再赋值。 对基本类型(int char …)进行retain是错误的。

@property (assign) classA *a;

等价于:

@property classA *a;

等价于:

- (void) setA : (classA *) newA {

   _a = newA;
}

- (classA *) getA {

   return _a;
}

但是这种实现方式,很有可能造成内存泄露(对象没有完全释放)这种问题。oc也给我们提供了一种安全的setter方式,就是使用retain参数,这样也避免了自己敲在setter中释放内存这段代码。

@property (retain) classA *a;

等价于:

- (void) setA : (classA *) newA {

  if (_a != newA) {

     [_a release];
     _a = newA;
  }
}

- (classA *) getA {

  return _a;
}

所以在声明OC对象的时候,更建议直接使用retain参数,避免自己重复在setter中写释放内存的代码。

copy参数会在setter中copy对象,与retain类似

@property (copy) classA *a;

等价于:

- (void) setA : classA *newA {

   if (_a != newA) {

      [_a release];
      _a = [newA copy]
   }
}

3. atomic / nonatomic

这对参数用于线程是否安全。atomic线程安全,nonatomic线程不安全。

虽然线程安全可以防止出现死锁,但是效率却降低了。所以,在开发过程中,用得最多的还是nonatomic参数。

@property classA *a;

等价于

@property (atomic) classA *a;

等价于:

- (classA *) getA {

    [_a retain];
    return [_a autorelease];
}

线程不安全的情况:

@property  (nonatomic) classA *a;

等价于:

- (classA *) getA {

    return _a;
}