Objective-C @property

Objective-C @property
===

我相信对于ios开发者来说,Objective-C的@property都是不太陌生的一个概念。不过最近我参加了一次面试,在问到相关问题的时候还是感觉如鲠在喉,可见一个简单的概念想要清晰的去解释还是需要深刻的理解。故而写这篇博客来巩固一下对于OC的@property的理解。

---
##@property是什么
@property是编译器的指令

什么是编译器的指令,编译器指令就是用来告诉编译器要做什么

@property 告诉编译器声明属性的访问器(getter/setter)方法

和@property配对使用的还有@synthesize指令

@synthesize指令:告诉编译器,生成或合成属性的访问器(getter/setter)方法

举例,原本我们需要写如下代码
```
@interface PropertyTest : NSObject    
{        
    NSString *name;    
}    
- (NSString *)name;    
- (void)setName:(NSString *)newName;    
@end
```
使用@property和指令后
```
@interface PropertyTest : NSObject    
{
    NSString *name;
}    
@property (nonatomic, strong) name; 
@end
```
看上去不错,简洁漂亮。

如果属性很多,@property能省下的代码量将会相当可观。

##@property的attribute
细心点的就会发现,每个@property括号后面都跟了一个括号,括号里面是什么东西呢?括号里面呢是@property的attribute,可以理解为@property的设置。

括号里面设置(attribute)不同,property所生成的setter方法也就不同。

有哪些设置呢?我简单列举一下:

   * 
atomic(默认):atomic意为操作是原子的,意味着只有一个线程访问实例变量。
   * 
nonatomic: nonatomic跟atomic刚好相反。表示非原子的,可以被多个线程访问。
   * 
readwrite(默认):readwrite是默认的,表示同时拥有setter和getter。
   * 
readonly: readonly 表示只有getter没有setter。
   * 
retain:释放旧值,retain新值
   * 
assign(默认):用于值类型,如int、float、double和NSInteger,CGFloat等表示单纯的复制。还包括不存在所有权关系的对象,比如常见的delegate。
   * 
strong:是在ARC伴随IOS引入的时候引入的关键字是retain的一个可选的替代。表示实例变量对传入的参数要有所有权关系即强引用。strong跟retain的意思相同并产生相同的代码,但是语意上更好更能体现对象的关系。
   * 
weak: weak跟assign的效果相似,不同的是weak在对象被回收之后自动设置为nil。而且weak智能用在iOS 5或以后的版本,对于之前的版本,使用unsafe_unretained。
   * 
copy:copy是为是实例变量保留一个自己的副本。

atomic/nonatomic readwrite/readonly的功能都相对来说好理解

剩下的attribute跟内存管理有点关系,下面我们讲点内存管理和@property的关系


---
##property和内存管理
内存管理听上去很高大上有木有,内存管理博大精深,不过内存管理是一个笼统的概念,并不是一个很专业的技术概念。在Objective-C里我们主要通过引用计数来达到内存管理的目的。

好吧,又来了一个概念叫引用计数。跟标题不符合啊!标题党啊!不要急,不要急,其实引用计数和内存管理是密不可分的。举一个二一点的例子。内存管理就是吃饱饭,那怎么样能吃饱饭呢?你吃米饭能吃饱,你吃面条也能吃饱。在OC里内存管理就是通过引用计数来完成,而在java里内存管理就是通过垃圾回收机制来完成。 所以接下来我们来讲讲引用计数。 

>引用计数 
>
>这是一种古老但有效的内存管理方式。每个对象(特指:类的实例)内部都有一个retainCount的引用计数,对象刚被创建时,retainCount为1,可以手动调用retain方法使retainCount+1,同样也可以手动调用release方法使retainCount-1,调用release方法时,如果retainCount值减到0,系统将自动调用对象的dealloc方法(类似于c#中的dispose方法),开发人员可以在dealloc中释放或清理资源。


上面一段话呢是从参考资料里复制出来的,简单的来说呢,当你创建一个对象的时候,对象里面就有了一个计数retainCount,初始值为1。当你对对象做一些操作的时候可以对这个retainCount的值做一些改变。那哪些操作可以更改这个计数呢? 简单列举一下:

   * 
retain 计数加1。
   * 
release计数减1
   * 
autorelease 计数减1,但是不是立即执行,而是以推迟的方式。

通过这些操作呢,我们对retainCount计数做出了修改,如果计数变为0的时候就会自动调用dealloc方法来释放对象和内存。

屁话讲了一堆,那property和内存管理有毛关系,或者说property和引用计数有毛关系。 好吧,开始进入正题了.

还记得上一节说的那个property的设置(attribute)吗 

某些attribute会生成不同的set方法。那些不同的set方法里就有跟内存管理相关的内容。 让我们来看看哪些设置是根内存管理有关系的,让我来一一列举出来。

**设置了assgin之后的setter方法**
```
- (void)setName:(NSString *)newName 
{ 
    name = newName;
}
```
**设置了retain之后的setter方法** 
```
- (void)setName:(NSString *)newName 
{ 
    if (newName != name) { 
        [name release]; // release旧值 
        name = [newName retain] //retain新值 
    } 
}
```
**设置了copy之后的setter方法**
```
- (void)setName:(NSString *)newName 
{ 
    if (newName != name) { 
        [name release]; // release旧值 
        name = [newName copy] //copy新值 
    } 
}
```

跟内存相关的呢主要是这三个attribute

还有两个attribute也要提及一下,就是 weak 和 strong

retain 和 strong 功能基本一致

weak能在对象自动销毁的时候自动赋值nil,主要用于解决循环应用的问题

property如果拥有以上设置,成员变量的get方法里就会有相应的retain和release操作。这就是为什么说property跟内存管理有关系了。

##PS
以上就是我对@property的简单理解,随着IOS开发的经验增加,对OC有更深入的理解后,我会继续补充。文章中可能有稍许纰漏,如果有疑问,烦请提出来一起讨论!


**参考资料**:

http://www.cnblogs.com/andyque/archive/2011/08/03/2125728.html
http://www.cnblogs.com/yjmyzz/archive/2011/02/23/1958961.html