完成属性定义后,编译器会自动编写访问这些属性所需的方法,此过程叫做“自动合成”(autosynthesis)。需要强调的是,这个过程由编译 器在编译期执行,所以编辑器里看不到这些“合成方法”(synthesized method)的源代码。除了生成方法代码 getter、setter 之外,编译器还要自动向类中添加适当类型的实例变量,并且在属性名前面加下划线,以此作为实例变量的名字。
我们每次在增加一个属性,系统都会在 ivar_list 中添加一个成员变量的描述,在 method_list 中增加 setter 与 getter 方法的描述,在属性列表中增加一个属性的描述,然后计算该属性在对象中的偏移量,然后给出 setter 与 getter 方法对应的实现,在 setter 方法中从偏移量的位置开始赋值,在 getter 方法中从偏移量开始取值,为了能够读取正确字节数,系统对象偏移量的指针类型进行了类型强转.
@property
@property(nonatomic,copy)NSString *name; 相当于是
1.声明了:
(NSString *)name;
(void)setName:(NSString *)str;
-
生成成员变量 _name
-
实现了:
(NSString *)name;
(void)setName:(NSString *)str;
- 对于@property的参数 如果是使用@property(nonatomic,copy,getter=familyName)NSString *name; 则是相当于get方法为:
(NSString *)familyName;
而实现的时候则为:
(NSString *)familyName{
return name;
}
readwrite: 产生setter\getter方法(默认参数)
readonly: 只产生简单的getter,没有setter。
assign: 默认类型,setter方法直接赋值,而不进行retain操作(默认参数)
retain: setter方法对参数进行release旧值,再retain新值。
copy: setter方法进行Copy操作,与retain一样
nonatomic: 禁止多线程,变量保护,提高性能
atomic:原子性的访问方法(默认参数)
@synthesize
先去访问同名变量; 如果没有定义NSString *_name; 相当定义了先NSString *_name; 再实现了:
(NSString *)name{
return _name;
}
(void)setName:(NSString *)str{
if(_name != str){
[_name release];
_name = [str retain];
}
}
自动合成没有任何内存的含义,所以它根本没有连接到ARC。
当然,如果自己本身就已经实现了
(NSString *)name;
(void)setName:(NSString *)str;
这两个方法,那么系统就不再实现了。
对于现在,如果不使用
@synthesize name = _name;
也默认是使用@synthesize name = _name;
@synthesize name;
如果使用的是@synthesize name;
那么对于上面的变量则为生成的是name而不是_name;
相当于是
(NSString *)name{
return name;
}
(void)setName:(NSString *)str{
if(name != str){
[name release];
name = [str retain];
}
}
@synthesize name = testName;
如果使用的是@synthesize name = testName;
则对于上面的变量则为生成的是testName而不是name,方法也对应改变,
总之:定义的变量是根据@synthesize name = xx;来定的。
注意:属性的setter方法和getter方法是不能同时进行重写的,这是因为,一旦你同时重写了这两个方法,那么系统就不会帮你生成这个成员变量了,所以会报错
@dynamic
@dynamic 告诉编译器:属性的 setter 与 getter 方法由用户自己实现,不自动生成。假如一个属性被声明为 @dynamic var,而且你没有提供 @setter方法和 @getter 方法,编译的时候没问题,但是当程序运行到 instance.var = someVar,由于缺 setter 方法会导致程序崩溃;或者当运行到 someVar = var 时,由于缺 getter 方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。
如果某属性已经在某处实现了自己的 setter/getter ,可以使用 @dynamic 来阻止 @synthesize 自动生成新的 setter/getter 覆盖。
注意
一种情形需要使用 @synthesize ,就是当在 protocol 中声明并实现属性时。协议中声明的属性不会自动生成setter和getter,[UIApplicationDelegate window] 就是个典型的例子。