刚开始学习ios的时候发现在头文件里面的变量都带有不同的属性,当时也没太在意他们的区别,但是心里始终都不踏实,所以专门写个博客把它们理解的同时也记录下来。
property作用
使用方法:
.h文件
@property NSString * name;
.m文件
@synthesize name = _name;
表达意思:表示生成了一个对外变量名为name的setter和getter方法。
补充说明:在 ios5.0后,@synthesize也可以省略不写,此时在.h文件中只写@property即可,编译器会自动生成相应的实例变量,实例变量的名字是属性名称前加下划线。
所有特性
readyonly、readwrite、atomic、nonatomic、assign、retain、copy、strong、weak、unsafe_unretained
特性分类
- 读写性(readyonly、readwrite)
- 原子性(atomic 、nonatomic)
- 管理性(assign、retain、copy、strong、weak、unsafe_unretained)
属性注意事项
- strong、weak、unsafe_unretain这几个属性是在ARC推出后新加的
- ARC环境下,对象内存管理不再使用retain、release、autorelease
特性讲解
读写性
(1) readwrite
描述:该类的默认属性,从字面能理解同时具有读/写操作,从代码上理解就是具有setter和getter。
(2) readyonly
描述:从字面能理解只具有读的操作,从代码上理解就是只有getter没有setter。
原子性
(1) atomic
描述:该类的默认属性,能保证多线程访问下的安全,但浪费系统资源,同时系统会为setter方法加锁。注意一点的是:atomic并不代表真正的线程安全。
(2) nonatomic
描述:非原子性访问,不同步,而且可以同时被多个线程访问。nonatomic效率相对较高,一般情况下都使用这个。
管理性
(1) assign
对象:该类的默认属性(ARC之前),主要面向基础数据类型(int,float,double等),以及基础数据的封装类NSInteger等。
原理:setter方法直接赋值,而不进行retain操作,对对象类型不会发生引用计数变化。
(2) retain
对象:除NSString以外其他NSObject和其子类
原理:setter方法对参数进行release旧值,再retain新值。Retain是指针复制(浅复制),引用计数加1,而不会导致内容被复制。
(3) copy
对象:NSString
原理:setter方法对参数进行release旧值,再Copy出新的对象,新对象的引用计数为1。Copy是复制内容(深复制),如果调用copy的是数组,则为指针复制(浅复制),仅仅复制子元素的指针。
(4) strong
对象:该类的默认属性(ARC之后)
原理:strong与retain类似,引用计数会自动+1。
(5) weak
对象:delegate比较常见,以防止循环引用。
原理:weak与assign类似,唯一区别是weak对象会销毁后自动设置为nil,而assign不会。声明为weak的指针,指针指向的地址一旦被释放,这些指针都将被赋值为nil。这样的好处能有效的防止野指针。
(6) unsafe_unretained
对象:比较少的使用
原理:从它的名字拆分来说,先是unretained代表与weak、assign类似,然后是unsafe,直接在代码里试了一下。当所指向的值被置空后,再使用unsafe_unretained类型的值将会闪退。原因是因为它与weak不同的地方是,当对象被释放后,不会被赋值为nil,所以导致闪退了。
临时变量的声明
对于变量来说也是可以添加对应的声明,具体的特性有:__strong、 __weak、 __unsafe_unretained、 __autoreleasing。
这四个特性前三个与前面介绍strong、weak、unsafe_unretained具有同样的功能。
(4) __autoreleasing
描述:说到__autoreleasing,可能大家会有个疑虑:与MRC时代的autorelease是否有关系。首先因为在ARC里面是不允许使用autorelease的,要记住这点,然后对于 __autoreleasing是针对变量使用的,官方的解释是适用于引用参数的传递当中( __autoreleasing is used to denote arguments that are passed by reference (id *) and are autoreleased on return.)
比较:下面两段代码目的是一样的
//在MRC中
NSString *str = [[[NSString alloc] initWithFormat:@"but"] autorelease];
//在ARC中
NSString *__autoreleasing str = [[NSString alloc] initWithFormat:@"but"];
讲解:error的使用
(1)一般用法
NSError *error;
BOOL OK = [myObject performOperationWithError:&error];
if (!OK) {
// Report the error.
// ...
(2)函数的命名格式
-(BOOL)performOperationWithError:(NSError * __autoreleasing *)error;
(3)编译器的运行
NSError * __strong error;
//自动添加
NSError * __autoreleasing tmp = error;
BOOL OK = [myObject performOperationWithError:&tmp];
//自动添加
error = tmp;
if (!OK) {
// Report the error.
// ...
(4)正确用法
NSError *__autoreleasing error;
BOOL OK = [myObject performOperationWithError:&error];
if (!OK) {
// Report the error.
// ...
(5)优点
__autoreleasing形式创建出来的error对象,会被放入到autoreleasing pool中,等函数执行完毕就会把对象自动释放,而函数外error的使用者则不需要担心error对象被释放的问题。