iOS基础知识整理之修饰符的使用和区别

修饰符的使用和区别

在ARC环境下,修饰符有assign,strong,weak,copy,readwrite,readonly,nonatomic,atomic

属性修饰符对引用计数(retainCount)的影响

  1. alloc为对象分配内存,retainCount为1;
  2. retain,retainCount+1;
  3. copy一个对象变成另一个对象,retainCount为1,原有对象计数不变;
  4. release,etainCount-1;
  5. autorelease,retainCount-1。

assign、retain、copy分别对应的setter方法

1
2
3
4
// assign
- (void)setAssignObject:(id)newValue {
assignObject = newValue;
}
1
2
3
4
5
6
7
// retain 
- (void)setRetainObject:(id)newValue {
if (retainObject != newValue) {
[retainObject release];
retainObject = [newValue retain];
}
}
1
2
3
4
5
6
7
// copy
- (void)setCopyObject:(id)newValue {
if (copyObject != newValue) {
[copyObjectrelease];
copyObject = [newValuecopy];
}
}

nonatomic和atomic的区别

atomic为默认属性,多线程安全,这个属性是为了保证程序在多线程情况下,编译器自动生成一些互斥加锁代码,避免该变量的读写不同步问题,对性能的消耗非常大;
nonatomic:禁止多线程,变量保护,提高性能。如果该对象无需考虑多线程的情况,建议加入此属性,这样会让编译器少产生一些互斥加锁代码,可以在一定程度上提高效率。

readwrite和readonly的区别

readonly表示这个属性是只读的,就是只生成 getter方法,不会生成setter方法。
readwrite表示可读写,生成getter和setter方法。

weak和strong的区别

默认情况下,一个指针都会使用strong属性,表明这是一个强引用。这意味着,只要引用存在,对象就不能被销毁。
weak是弱引用,使用weak修饰主要是为了解决循环引用的问题。

  1. 在修饰代理属性的时候使用weak;
  2. 通过连线方式创建控件时用weak;
  3. 在block中,为避免循环引用,使用weak修饰self,__weak typeof(self) weakSelf = self。

copy和strong的区别

当源字符串是NSString时,由于字符是不可变的,不论strong还是copy属性,都是指向源对象,copy操作只是做了次浅拷贝。
当源字符串是NSMutableString时,strong属性只是增加了源字符串的引用计数,而copy属性则是对源字符串做了次深拷贝,产生了一个新的对象,且copy属性对象指向这个新的对象。另外需要注意的是,这个copy的属性对象的类型始终是NSString,而不是NSMutableString,因此其是不可变的。这里strong属性只是单纯增加对象的引用计数,而copy操作则进行了一次深拷贝,所以性能上有所差异。

assign和weak的区别

assign适用于基本数据类型,weak适用于NSObject对象,并且是弱引用。当assign用来修饰对象时容易造成野指针,对象一般会分配在堆上的某块内存,如果在后续的内存分配中,刚好分到了这块地址,程序就会崩溃。
之所以assign可以用来修饰基本数据类型,是因为基础数据类型一般分配在栈上,栈的内存会由系统自己自动处理,不会造成野指针。
weak修饰的对象在被释放以后,指针地址会被置为nil,所以现在一般弱引用就是用weak。

block变量定义时用copy

block的循环引用并不是strong导致的,在ARC环境下,系统底层也会做一次copy操作使block从栈区复制一块内存空间到堆里,所以strong和copy在对block修饰上没有本质区别,只不过copy操作的效率高而已,一般用copy来修饰block。