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