类的属性和实例变量是两个概念
类的属性声明通过关键字@property声明, 编译器在编译阶段将自动:1.为属性创建一个相对应的实例变量2.为属性创建getter,setter方法(getter,setter方法内部实际是存取背后的实例变量)。
注意,此时该类的实例对象。不仅有一个 私有的实例变量,而且还有一个 属性。可以对该属性直接进行getter,setter。说白了,该 属性 是相对应 私有实例变量 的外包装。用于封装内部的 实例变量。
声明为属性有诸多优点
声明为属性有很多好处,有许多配套的限定词,来令编译起自动帮你完成一些功能。
专为 属性 创造的 点运算符
通过'.'运算符,可以快速调用该属性的setter,getter方法。
限定词
(readwrite) || (readonly)
(getter = anotherName) 另命名属性的getter方法,取代原先的 setPropertyname 的方法
@synthesize
通过 @synthesize 可以显式指定属性背后的实例变量的名字:
1. @synthesize propertyA = _a ; 将背后的实例变量命名为_a
2.@synthesize propertyA ; 将背后的实例变量命名为与 属性 相同的名字
3.不实用@synthesize 声明。系统自动命名 实例变量 的名字为 _propertyA
自定义存取器方法
也可以根据需要手动定义 属性 的存取方法,例如
@property (readonly) NSString *fullName;
自动生成的话,就会生成一个仅仅返回 fullName 字符串的变量值。如果自定义的话:
- (NSString *)fullName {
return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}
就可以,在每次get fullName属性时,得到最新的fullName属性值。通过这种方式,属性 不一定需要有自己专属的 实例变量。
注意
编译器会自动声明实例变量与相对应的属性。但当你自定义了属性的getter和setter方法时,编译器会认为你已经掌控了属性的相关实现,就不会在为其自动创建相关联的实例变量。经测试,这个的确是个问题。如果实在需要的话,需要显式声明:
@synthesize property = _property;
经过测试,在不使用@synthesize语句的前提下。setter和getter方法若只声明其一,编译器还是会自动为@property声明的属性定义背后的实例变量。但只要是写了setter和getter方法,编译器就会报错。说没有找到该实例变量。
跟踪属性值的变化
类的成员属性,会被跟踪值的变化。如果不声明为属性,则实例变量无法被跟踪。
在初始化函数中不能通过getter,setter方法访问属性
在初始化函数中,永远要直接访问实例变量。因为存取函数可能会遭到子类的复写
存取方法的限定词
(readwrite) || (readonly):默认是readwrite
(atomic) || (nonatomic) : 默认为atomic,原子性保证属性是否可以同一事件被不同线程访问。
不通过声明属性的方式,创建类的实例变量
如果不想将 实例变量 声明为属性,则在@interface 或 @implementation 处,在大括号内声明实例变量。
在@interface的大括号中声明的变量,可以通过标记@public, @protect , @private 来表明他们的访问和继承规则。默认为@protect。
在@implementation大括号中声明的变量,一律为@private。即使使用了@public的限定词,也是失效的。