@property是什么
@Property是声明属性的语法,它可以快速方便的为实例变量创建存取器,并允许我们通过点语法使用存取器。
存取器(accessor):指用于获取和设置实例变量的方法。用于获取实例变量值的存取器是getter,用于设置实例变量值的存取器是setter。
创建存取器
手工创建存取器
我们先看两段代码:
//Fraction.h
#import <Foundation/Foundation.h>
@interface Fraction:NSObject
{
int numerator;
int denominator;
}
-(void) print;
-(void) setNumerator: (int) n;
-(void) setDenominator: (int) d;
-(int) numerator;
-(int) denominator;
-(double) convertToNum;
上面代码中numerator、denominator是Fraction类的实例变量,并且看到对这两个实例变量都声明了set/get方法。
//Fraction.m
#import "Fraction.h"
@implementation Fraction
-(void) print
{
NSlog (@"%i/%i", numerator, denominator);
}
-(void) setNumerator: (int) n
{
numerator=n;
}
-(void) setDenominator: (int) d
{
denominator=d;
}
-(int) numerator
{
return numerator;
}
-(int) denominator
{
return denominator;
}
-(double) convertToNum
{
if (denominator != 0)
return (double) numerator / denominator;
else
return 1.0;
}
@end
上面代码是对实例变量存取器的实现。我们可以看到,存取器就是对实例变量进行赋值和取值。按照约定赋值方法以set开头,取值方法以实例变量名命名。
使用@Property创建存储器
@interface Fraction:NSObject
{
int numerator;
int denominator;
}
@property int numerator, denominator;
-(void) print;
-(double) convertToNum;
上面代码中,我们使用@property声明两个属性,名称与实例变量名称相同。
@implementation Fraction
@synthesize numerator, denominator;
-(void) print
{
NSlog (@"%i/%i", numerator, denominator);
}
-(double) convertToNum
{
if (denominator != 0)
return (double) numerator / denominator;
else
return 1.0;
}
@end
和手动生成存取器相比,在.m文件中我们使用@synthesize自动生成这两个实例变量的存取器,并且隐藏了存取器,虽然我们看不到存取器,但它们确实是存在的。
总结:
@property等同于在.h文件中声明实例变量的get/set方法,@synthesize等同于在.m文件中实现实例变量的get/set方法。使用@property和synthesize创建存取器要比手动声明两个存取方法(getter和setter)更简单。而且我们在使用属性时可以使用点语法赋值或取值,语法更简单,更符合面向对象编程。
不必单独声明实例变量
如果我们希望使用默认的实例变量命名方式,那么我们在.m文件中就不需要使用@synthesize声明,系统会帮我们自动完成(以“_实例变量名字”来命名)。
@synthesize numerator = _numerator;
@synthesize denominator = _denominator;
如果我们希望自己命名实例变量命,那么我们就使用@synthesize显示声明我们希望的实例变量名。
@property的特性
@property还有一些关键字,它们都是有特殊作用的,比如上述代码中的nonatomic,strong。
把它们分为三类,分别是:原子性,存取器控制,内存管理。
原子性
atomic(默认):atomic意为操作是原子的,意味着只有一个线程访问实例变量。atomic是线程安全的,至少在当前的存取器上是安全的。它是一个默认的特性,但是很少使用,因为比较影响效率,这跟ARM平台和内部锁机制有关。
nonatomic:nonatomic跟atomic刚好相反。表示非原子的,可以被多个线程访问。它的效率比atomic快。但不能保证在多线程环境下的安全性,在单线程和明确只有一个线程访问的情况下广泛使用。
存取器的控制
readwrite(默认):readwrite是默认值,表示该属性同时拥有setter和getter。
readonly: readonly表示只有getter没有setter。
内存管理
主要涉及到assign、retain、strong、weak、copy等情况,以及各自的使用场景。
Strong:强引用,表示实例对象对传入的对象有所有权关系。常用在:自定义对象,控制器对象。
Weak:弱引用,在setter方法中,需要对传入的对象不进行引用计数加1的操作,也就是,对传入的对象没有所有权,当该对象的引用计数为0时,该对象即被释放,用weak声明的实例变量指向nil,即实例变量的值为0。常用在:delegate对象,IBOutLet。
Assign:简单赋值,不改变引用计数,适合简单数据类型如NSInteger、CGFloat、int、float等。
Copy:把原来的对象完整复制另外一个地方,重新加载内存区,原来对象变了不影响新内存区的对象。常用在:NSString、NSArray、NSDictionary及其子类等。