@property的概念
@property = ivar + getter + setter;
@Property是声明属性的语法,作为 Objective-C 的一项特性,主要的作用就在于封装对象中的数据。它可以快速方便的创建实例变量,并为实例变量创建存取器,并允许我们通过点语法使用存取器。
存取器(accessor):指用于获取和设置实例变量的方法。用于获取实例变量值的存取器是getter,用于设置实例变量值的存取器是setter。
@synthesize
Xcode4.4 之前,如果你没有手动实现 setter 方法和 getter 方法,需要使用@synthesize生成 setter 和 getter 方法,Xcode4.4之后,@property使用“自动合成”( autosynthesis)生成ivar、getter、setter并添加到类中。
完成属性定义后,编译器会自动编写访问这些属性所需的方法,此过程叫做“自动合成”(autosynthesis)。需要强调的是,这个过程由编译器在编译期执行,所以编辑器里看不到这些“合成方法”(synthesized method)的源代码。除了生成方法代码 getter、setter 之外,编译器还要自动向类中添加适当类型的实例变量,并且在属性名前面加下划线,以此作为实例变量的名字。也可以在类的实现代码里通过 @synthesize 语法来指定实例变量的名字。
@synthesize 合成实例变量的规则
1.如果指定了成员变量的名称,会生成一个指定的名称的成员变量
2.如果这个成员已经存在了就不再生成了.
3.如果实现了@synthesize,但没有指定成员变量的名称,会自动生成一个与属性同名的成员变量。
@dynamic
@dynamic 告诉编译器:属性的 setter 与 getter 方法由用户自己实现,不自动生成。(当然对于 readonly 的属性只需提供 getter 即可)。假如一个属性被声明为 @dynamic var,然后你没有提供 @setter方法和 @getter 方法,编译的时候没问题,但是当程序运行到 instance.var = someVar,由于缺 setter 方法会导致程序崩溃;或者当运行到 someVar = var 时,由于缺 getter 方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。
@property的特性关键字
原子性
- atomic(默认):原子的,线程安全的,系统会自动加上同步锁(多个线程在写入原子属性时(调用 setter 方法),能够保证同一时间只有一个线程执行写入操作,但是同一个时间多个线程都可以取值),影响效率,使用少。
- nonatomic:非原子的,线程不安全的,效率高,使用广泛。
存取器控制
- readwrite(默认):readwrite是默认值,表示该属性同时拥有setter和getter。
- readonly: readonly表示只有getter没有setter。
内存管理
- assign(默认): 用于基本数据类型,如 int、float、double、NSInteger、CGFloat 等。在 setter 方法中采用直接赋值来实现设值操作:
-(void)setRunning:(int)newRunning{
_running = newRunning;
}
- strong:强引用,对传入对象拥有所有权。在setter方法中,需要对传入的对象进行引用计数加1的操作:
-(void)setName:(NSString*)_name{
//首先判断是否与旧对象一致,如果不一致进行赋值。
//因为如果是一个对象的话,进行if内的代码会造成一个极端的情况:当此name的retain为1时,使此次的set操作让实例name提前释放,而达不到赋值目的。
if ( name != _name){
[name release]; //释放旧对象
name = [_name retain]; //引用计数加1后,设置新对象
}
}
- weak:弱引用,对传入对象没有所有权。在setter方法中,对传入的对象不进行引用计数加1的操作,并且既不保留新值也不释放旧值。当对象释放后,将对象指针设置为 nil。必须用于 OC 对象。
在 ARC 中,在有可能出现循环引用的时候,往往要通过让其中一端使用 weak 来解决,比如: delegate 代理属性
自身已经对它进行一次强引用,没有必要再强引用一次,此时也会使用 weak,(例如自定义 IBOutlet 控件属性一般使用 weak,因为控件已经被控制器的子视图强引用,没有必要再让控制器强引用一次);当然,也可以使用strong(使用 strong 不会造成强引用循环,因为当控制器释放后,其子视图也会释放,没有强指针指向控件)。
- copy:与 strong 类似。但在setter方法中,不保留新值,而是将其拷贝,并对传入的对象进行引用计数加1的操作。
用 @property 声明 NSString、NSArray、NSDictionary 经常使用 copy 关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary,他们之间可能进行赋值操作,为确保对象中的字符串值不会无意间变动,应该在设置新属性值时拷贝一份,拷贝的对象是不可变的。