天天看点

[email protected]和@synthesize

对于iOS的开发, 是一个逐渐学习理解的过程. 

下面说一下对于Objective-C 中的 @property和@synthesize的理解。

在这之前先讲讲访问器(Accessor),也就是我们所知道的setter和getter方法。《Cocoa Design Patterns》中的将它归类为基础模式中的一种。访问器是很重要的技术,用来访问和设置对象的实例变量(不是指对象本身,而是对象中的属性)。有时候可能需要用不同的方式或者通过计算等方式来获取或设置实例变量,访问器给了我们很大的灵活性。在Cocoa中访问器有很多的优点:

1. 实现灵活性。 可以在访问器中改变并实现不同的实例变量访问方式而不影响其他代码。

2. 可维护性。通过访问器对实例变量的更改易于维护。

3. 内存管理。访问器方法提供了简单的方法去遵守Cocoa的约定把内存管理代码隔离在少部分代码中。

4. 支持KVC和KVO。 KVC和KVO是很强大的技术。但是它们依赖于正确命名访问器。

下面这段代码简单的实现了一个访问器(setter和getter):

//setter

-(void)setName:(NSString *)name

{  //_name 是实例变量

    if(_name != name)

    {

        [_name release];

        _name = [_name retain];

    }

}

//getter

-(NSString *)name

{

    return _name;

}

上面代码中的setter中还涉及到一定的内存管理,这个技术很重要,那么有没有一种更方便的方法去做呢?

答案就是@property和@synthesize。它们是Objective-C 2.0加入的指令,前者用于声明,后者用于合成访问器,结合使用就可以自动生成访问器了。

下面这段代码使用@property和@synthesize:

@property (nonatomic, copy) NSString *name;

@synthesize name = _name;

在@property中还有其他几个关键字,它们都是有特殊作用的,将它们分为三类分别是:原子性,访问器控制,内存管理。

1. 原子性

    atomic(默认):atomic意为操作是原子的,意味着只有一个线程访问实例变量。atomic是线程安全的至少在当前的访器上我是安全的。它是一个默认的,但是很少使用。它的比较慢,这跟ARM平台和内部锁机制有关。

    nonatomic: nonatomic跟atomic刚好相反。表示非原子的,可以被多个线程访问。它的速度比atomic快。但不能保证在多线程环境下的安全性,在单线程和明确只有一个线程访问的情况下广泛使用。

2. 访问器控制

    readwrite(默认):readwrite是默认的,表示同时拥有setter和getter。

    readonly: readonly 表示只有getter没有setter。

3. 内存管理

    retain:使用了retain意味着实例变量要获取传入参数的所有权。具体表现在setter中对实例变量先release然后将参数 retain之后传给它。下面这段代码展示了retain类似的行为:

-(void)setStuName:(NSString *)stuName

{

    if(_stuName != stuName)

    {

        [_stuName release];

        _stuName = [stuName retain];

    }

}

    assign(默认):用于值类型,如int、float、double和NSInteger,CGFloat等表示单纯的复制。还包括不存在所有权关系的对象,比如常见的delegate。

    strong:是在ARC伴随IOS引入的时候引入的关键字是retain的一个可选的替代。表示实例变量对传入的参数要有所有权关系即强引用。strong跟retain的意思相同并产生相同的代码,但是语意上更好更能体现对象的关系。

    weak: weak跟assign的效果相似,不同的是weak在对象被回收之后自动设置为nil。而且weak智能用在iOS 5或以后的版本,对于之前的版本,使用unsafe_unretained。

    unsafe_unretained:weak的低版本替代。

    copy:copy是为是实例变量保留一个自己的副本。