在Objective-C中引入了属性这个概念,当然了这东西并不是Objective-C首创而且独有的特性,例如C#里边也有属性的概念,因此学过C#的朋友应该很容易就掌握Objective-C中的属性这个知识点。
1 OverView
在java中,我们可能经常通过getter/setter来访问一个对象的成员变量,为什么不直接访问对象内部的成员变量了,这样不是更简单吗?因为通过getter/setter的这种模式来间接地访问对象的成员变量,符合了类的封装性的原则。这就好像汽车一样,你不是直接操作汽车的引擎、油门阀、制动器来驾驶汽车,因为这些东西(成员变量)都被汽车(类)的设计者封装起来了,不直接向外界暴露,而是通过提供诸如像方向盘、刹车的踏板、油门踏板(getter/setter)这样的接口来供外界使用,这样就隐藏了类内部的一些实现细节。。
既然写getter/setter方法有这么多好处,好吧,那我们以后设计每个类都这样做,结果悲催了,因为有一天公司叫你设计一个类,而那个类有10W个成员变量,这就意味着你要写10W对getter/setter对(当然了现实中可能不存在这样子的极限情况)。想想都觉得好蛋疼。好吧,对于这样中情况,Objectiv-C的设计团队隆重地在其语言特性中提供了Property的机制,以减轻我们的工作量,同时也使得代码变得更简洁。
Objective-C教导我们:你要是想用这种机制来偷懒,好吧,你必须提供以下信息才可以哦:
一、属性的类型和名称(废话,不然编译器肿么自动帮你生成getter/setter)
二、指顶Property的属性,以控制生成getter/setter的具体行为。
2 Property的声明和实现
要在Objective中使用Property,那么我们得分两步走:声明它然后定义它。
2.1 Property的声明
我们可以通过关键字@property来声明属性,而且属性的声明可以出现在类中的方法列表的任何位置,也可以出现在协议声明的任何位置。
格式:@property(属性集)type name;
2.2 属性集
2.2.1 读写性:
readwrite(读写属性:指示编译器生成getter和setter方法,此属性是默认的)
readonly(只读属性:指示编译器只生成getter方法)
2.2.2 针对setter方法的属性
strong:强引用,相当于retain。
weak:弱引用,相当于assign,且弱引用所指向的对象被释放后,指向该对象的指针会被自动置为nil.
copy:指定setter方法的参数采用深度复制到目标对象上,但是setter方法的参数必须要实现NSCopying协议(协议只是Objective-C中的叫法,即接口啦)
assign:指定setter方法中只是简单的复制,此属性为默认属性。例如对一些基础类型的属性可以采用它,如int,float,NSInteger....
retain:在assign基础上,再保留setter参数的一个引用,造成的影响是setter参数中的对象的保留计数值增加了1
此属性适用于参数为某一个对象的指针。如NSString*,
2.2.3Atomicty即原子性,
nonatomic属性:指定对属性的访问是非原子性的,默认是atomic原子性的。
atomic属性:指定对属性的访问时原子性的。此属性为默认值
一般为了在多线程环境中,提供健壮的属性访问,可以将property的属性指明为atomic,这样就不会再get的同时,也有另外一个线程在对同一个property进行set操作。但这样做虽然安全了,但牺牲了效率。鱼与熊掌不可兼得呀。
如果你指定了property的属性集为strong、copy或者是retain,但没有指定nonatomic,那么在引用计数的环境中,编译器会为该property生成类似于如下的getter方法:
[_internal lock]
id result = [[value retian] autorelease];
[_internal unlock]
return result;
2.2.4 getter和setter属性
我们可以自定义getter和setter的名字
eg: @property(getter=MyName,setter=setMyName) NSString* name;
这样编译自动生成的getter和setter方法名就会按你指定的那样:setMyName和MyName;
3 property的实现
我们可以通过@synthesize 或者@dynamic来通知编译器按照property的声明部分指定的条件来生成对应的getter/setter。
3.1 @synthesize
@synthesize 属性名[=成员变量名]; “[]”表示里面的内容是可选的。。
第一种形式:不带中括号中的内容的定义方法
eg: @interface Student:NSObject
{
NSString* name;
}
@property(nonatomic,retain) NSString* name;
@implementation Student
@synthesize name; //自动生成setName和name方法
第二种方式
在声明部分改为:@property(nonatomic,retain)NSString* myProperty;
@implementation Student
@synthesize myProperty=name; //=name表示在合成的setMyProperty和myProperty中操作的成员变量是name;
3.2@dynamic
关键字@dynamic其实就是告诉编译器在运行时动态地去找setter或者getter方法。因为代码由我们自己实现了或通过继承而来。(个人理解)
eg:
3.2.1@dynamic小技巧:
我们可以通过它在子类中改变父类中的只读属性。例如:
@interface A:NSObject
{
int nTmp;
}
@property(assign,readonly) int nTmp; //声明一个只读属性
@interface B:A
@property(readwrite,assign) nTmp;
@implementation B
@dynamic nTmp;
-(void)setNTmp:(int)newNTmp
{
nTmp = newNTmp;
}