Property 的参数(1)

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


环境信息
Mac OS X : 10.9
Xcode : 5.1.1

正文:

一. 首先,@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;
}