属性是可以说是面向对象语言中封装的一个体现,在自定义类中设置属性就相当于定义了一个私有变量、设置器(setter方法)以及访问器(getter方法),其中无论是变量的定义,方法的声明和实现都是系统自动生成的并且经过了相应地内存管理和优化,无需开发者操心。
属性的声明:
属性一般定义在类的接口,或类的延展内,并且放在方法的声明之前,成员变量的声明之后。属性关键字是@property,括号内的是属性的属性,然后是变量的类型和名字,属性的定义一般分为两种情况,一种是非对象类型的变量,如int整型,使用assign,第二种是对象类型的变量,使用retain或copy,若对象类型的变量是代理,则使用assign。
属性的属性包括:
1、原子性属性:
nonatomic:非原子性,在多线程下读写速度较快但不安全。
atomic:原子性,在多线程下同一时间只允许一条线程进行访问,保证数据安全。默认。
2、语义属性:
assign:直接赋值,适用于基本数据类型和代理。
retain:赋值是使引用计数加1,适用于除代理的所有对象类型。
copy:赋值时创建一个副本,适用于除代理的所有对象类型,但会占用较多内存,谨慎使用。
3、读写属性:
readwrite:可读写,自动生成设置器和访问器。默认
readonly:只读,只生成访问器。
getter=方法名:指定访问器的方法名。
setter=方法名:指定设置器的方法名。
点语法:
per.name=? 相当于调用属性name的setter方法,?=per.name 或 per.name相当于调用name属性的getter方法。
多重点语法:首先per对象有一个Student* 的对象,这个对象又带有NSString*类型的name属性
这种情况下是先调用per属性stu的getter方法,再调用stu属性name的setter方法。
属性setter方法和getter方法的内部实现和重写:
以@property (assign,nonatomic) int age;为例
setter方法:-(void)setAge:(int)age;
getter方法:-(int)age;
内部实现:属性在默认情况下声明的私有变量名为属性名前加下划线如_age,同时在默认情况下只能重写setter和getter的其中之一,若要重写两者要实现文件加上
@synthesize关键字,如@synthesize age = _age;
@property (assign,nonatomic) int age;
@property (retain,nonatomic) NSString *name;
@property (copy,nonatomic) NSString *sex;
设置为assign的属性就是直接赋值,不必细说,而设置为retain或copy的属性都是经过内存管理和优化,所用一般用于对象类型,而代理使用assign是因为被代理方本身不持有代理的所有权,所以不需要对代理的内存进行操作,直接赋值即可,而除了代理,因为对象对自己的私有变量持有所有权,所以要对私有变量进行内存管理。在setter方法中,若不对旧值所占用内存进行释放,便会造成内存泄露,若不对新值进行retain或copy,当参数所用内存在方法外部释放时,该属性便会成为野指针。在getter方法中,若不进行retain或copy就进行return,当对象被释放后便会存在野指针,若不进行autorelease便会造成内存泄露。