属性修饰符分析
基础概念
atomic & nonatomic
决定编译器生成的setter/getter是否为原子操作 。
atomic是Objc使用的一种线程保护技术,防止在某个操作未完成时被另外一个线程操作,造成数据错误。然而这种多线程安全机制对资源的占用很大,在iPhone等小型设备中,除非需要使用多线程之间通讯编程,采用这种技术需要慎重考量。
一般情况下,使用nonatomic来修饰成员变量,存取器直接返回一个值,而不需要管当不同的线程同时访问时会发生什么。
readwrite & readonly
任何属性都可以声明为readwrite或readonly,且默认设置为readwrite 。
将一个属性声明为readwrite时,编译器将会为这个属性生成setter和getter。
将一个属性生命为readonly时,编译器将只会生成getter。
assign
直接赋值,不更改引用计数,一般用于基础数据类型和C语言类型数据。
retain
释放旧对象,并使传入的新对象引用计数+1。
此属性只能用于NSObject及其子类,而不能用于Core Foundation(因为其没有使用引用计数,需要另外使用CFRetain和CFRelease来进行CF的内存管理)。
strong
释放旧对象,并使传入的新对象引用计数+1。
在ARC下,strong为对象类型属性声明时的默认值。
copy
创建一个引用计数为1的新对象,这个新对象是传入对象的拷贝。
会拷贝传入的对象(即创建一个引用计数为1的新对象,但是内容与传入对象相同),并把新对象赋值给实例变量。
weak
弱引用,要求不保留传入的属性(既不会使传入的对象引用计数+1)。
类似于assign,但与assign不同的是,当它们指向的对象被释放后,weak会被自动置为nil,而assign则不会。
进阶问题
strong & weak
这里采用 stack overflow 上的一个对强/弱引用的解释
如果将对象想象成一只想要逃跑(be deallocated)的狗的话。
强引用就像是拴住狗的绳子。只要你还还牵着拴住狗的绳子,狗就逃跑不了。如果有五个人都将绳子拴住了狗,那么除非五个人都解开了绳子,否则狗就不可能逃跑。
而弱引用,就像一个小孩子指着狗说:看,那里有一直狗。只要狗仍被狗绳拴着,小孩就还能看见狗,他们仍会指着它。然而一但狗绳被解开,狗就会逃跑而不管多少小孩子指着它。
copy & retain
copy实际上是建立了一个新的相同的对象,而retain是将传入对象的引用计数+1 。
深拷贝 & 浅拷贝
浅拷贝就是对内存地址的复制,让目标对象指针和源对象指向同一片内存空间 。浅拷贝只是对对象的简单拷贝,让几个对象共用一片内存,当内存销毁的时候,指向这片内存的几个指针需要重新定义才可以使用,要不然会成为野指针。
在iOS中,使用retain修饰的属性变量,就是一种浅拷贝。它既让几个指针共用同一片内存空间,又可以在release时由于计数的存在,不会轻易的销毁内存,达到更加简单使用的目的。
深拷贝是指拷贝对象的具体内容,而内存地址是自主分配的,拷贝结束之后,两个对象虽然存的值是相同的,但是内存地址不一样,两个对象也互不影响,互不干涉。
值得注意的是,对可变对象如NSMutableArray等无论是copy还是mutableCopy都是进行了深拷贝。
@property & @synthesize
如果我们希望使用默认的实例变量命名方式,那么我们在.m文件中就不需要使用@synthesize声明,系统会帮我们自动完成。如果我们希望自己命名实例变量命,那么我们就使用@synthesize显式声明我们希望的实例变量名 。
block作为实例变量为何要用copy修饰?
因为block如果在栈上的话,其所属的变量作用域结束,该block就被释放掉,block中的__block变量也同时被释放掉。为了解决栈块在其变量作用域结束之后被释放掉的问题,我们就需要把block复制到堆中。
为什么NSString、NSDictionary、NSArray要使用copy修饰?
对于NSString、NSDictionary、NSArray等经常使用copy关键字,是因为它们有对应的可变类型:NSMutableString、NSMutableDictionary、NSMutableArray,它们之间可能进行赋值操作,为确保对象中的字符串值不会无意间变动,应该在设置新属性时拷贝一份。
weak、copy、strong、assgin分别用在什么地方?
什么情况下会使用weak关键字?
- 在ARC中,出现循环引用的时候,会使用weak关键字。
- 自身已经对它进行了一次强引用,没有必要再强调引用一次。
assgin适用于基本的数据类型,比如NSInteger、BOOL等。
NSString、NSArray、NSDictionary等经常使用copy关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary;
除了上面的三种情况,剩下的就使用strong来进行修饰。