我用了不到一周的时间学习了Objective-C,后面的大部分时间我都在了解如何使用IOS的SDK和一些高级的话题,到目前已经有两个多月的时间了。目前能作一些简单的应用,可是在写代码的时候明显感受到基础不够扎实,毕竟一周的时间只能对一门语言有个概览。要想精通一门语言是远远不够的。 html
因此我把本身学习过程当中遇到的一些问题整理在博客上,这也是一个学习理解的过程。 安全
今天要说的内容是Objective-C 中的 @property和@synthesize。在这以前先讲讲访问器(Accessor),也就是咱们所知道的setter和getter方法。《Cocoa Design Patterns》中的将它归类为基础模式中的一种。访问器是很重要的技术,用来访问和设置对象的实例变量(不是指对象自己,而是对象中的属性)。有时候可能须要用不一样的方式或者经过计算等方式来获取或设置实例变量,访问器给了咱们很大的灵活性。在Cocoa中访问器有不少的优势: 多线程
下面这段代码简单的实现了一个访问器(setter和getter): app
//setter -(void)setStuName:(NSString *)stuName { //_stuName 是实例变量 if (_stuName != stuName) { [_stuName release]; _stuName = [stuName copy]; } } //getter -(NSString *)stuName { return _stuName; }
上面代码中的setter中还涉及到必定的内存管理,既然这个技术这么重要,那么有没有一种更方便的方法去作呢?答案就是@property和@synthesize。它们是Objective-C 2.0加入的指令,前者用于声明,后者用于合成访问器,结合使用就能够自动生成访问器了。 学习
下面这段代码使用@property和@synthesize: ui
@interface Student : NSObject @property (nonatomic, copy) NSString *stuName; @end @implementation Student @synthesize stuName = _stuName; @end
这段代码的效果跟上面代码的效果是同样的,是否是很方便呢? atom
使用@property和@synthesize很方便,但又给咱们带来了不少疑问好比在上面的代码中又出现了nonatomic和copy,是什么意思?在@property中还有其余几个关键字,它们都是有特殊做用的,我把它们分为三类分别是:原子性,访问器控制,内存管理。 spa
原子性 线程
atomic(默认):atomic意为操做是原子的,意味着只有一个线程访问实例变量。atomic是线程安全的至少在当前的访器上我是安全的。它是一个默认的,可是不多使用。它的比较慢,这跟ARM平台和内部锁机制有关。 code
nonatomic: nonatomic跟atomic恰好相反。表示非原子的,能够被多个线程访问。它的速度比atomic快。但不能保证在多线程环境下的安全性,在单线程和明确只有一个线程访问的状况下普遍使用。
访问器控制
readwrite(默认):readwrite是默认的,表示同时拥有setter和getter。
readonly: readonly 表示只有getter没有setter。
有时候为了语意更明确可能须要自定义访问器的名字:
@property (nonatomic, setter = mySetter:,getter = myGetter ) NSString *name;最多见的是BOOL类型,好比标识View是否隐藏的属性hidden。能够这样声明
@property (nonatomic,getter = isHidden ) BOOL hidden;要注意修改setter或者getter的名字是存在反作用的,可能会使KVC和KVO没法正常工做。
内存管理
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是为是实例变量保留一个本身的副本。
如今明白了@property是怎么回事了,可是@synthesize是怎么回事,看看以前的第一段代码:
@synthesize stuName = _stuName;这里的stuName = _stuName是什么意思?stuName是propertyName跟@property声明的名字同样。然后面的_stuName 是实例变量名。生成的访问器就是来访问的 _stuName的。代码的样子就和最开始那setter和getter代码所描述的同样。
注意一个问题,咱们并无声明_stuName这个变量,这是编译器自动帮咱们建立的。 若是这段指令我换个写法:@synthesize stuName = a; 而且咱们没有在interface里面声明这个变量,那么会自动建立一个变量a。
若是这里写成这样:
@synthesize stuName; //等同于 @synthesize stuName = stuName;
在Xcode4.4中,Xcode添加的一些新的编译特性。其中一个就是默认合成(Default Synthesis)。默认合成就再也不须要显示的使用@synthesize指令了,这很方便可是要注意的是,默认合成遵照的约定,这里的也就是命名规则是propertyName = _propertyName。
下面一段代码帮助理解:
//对于下面的@propety @property (nonatomic, copy) NSString *stuName; //默认合成的规则是这样: @synthesize stuName = _stuName;
以上是我所了解的@property和@synthesize,若是跟你的理解不一样,或者有什么错误,请给我留言:)。