一、简介
ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain、release、autorelease语句。你不再需要担心内存管理,因为编译器为你处理了一切
注意:ARC 是编译器特性,而不是 iOS 运行时特性(除了weak指针系统),它也不是类似于其它语言中的垃圾收集器。因此 ARC 和手动内存管理性能是一样的,有时还能更加快速,因为编译器还可以执行某些优化
二、原理
ARC 的规则非常简单:只要还有一个变量指向对象,对象就会保持在内存中。当指针指向新值,或者指针不再存在时,相关联的对象就会自动释放。这条规则对于实例变量、synthesize属性、局部变量都是适用的
1、强引用和弱引用
- 强引用:当前对象被其他对象引用时,会执行retain操作,引用计数器+1。当retainCount=0时,该对象才会被销毁。因为我们要进行对象的内存管理,所以这是默认的引用方式。(默认是强引用)
- 弱引用:当前对象的生命周期不被是否由其他对象引用限制,它本该什么时候销毁就什么时候被销毁。即使它的引用没断,但是当它的生存周期到了时就会被销毁。
注:
在定义属性时,若声明为retain类型的,则就是强引用;若声明为assign类型的,则就是弱引用。
后来内存管理都由ARC来完成后,若是强引用,则就声明为strong;若是弱引用,则就声明为weak。
2、内存泄漏
- 由于默认的引用方式是强引用,但为了避免内存泄漏(“强引用循环“的僵局)有时我们还得使用弱引用,那是什么情况呢?
答案,强引用循环:A对象强引用了B对象,B对象也强引用了A。因为都是强引用,也就是无论是A是B都要在对方的引用断了后才能销毁,但要断了引用,就必须对方对象销毁。就会出现这种僵局,为了避免出现这种情况,就应该有一个对象“示弱”,使其为“弱引用”。
比较常见的,视图中的父子视图之间的引用:父视图强引用子视图,子视图弱引用父视图。
三、@property 属性声明
1、首先我们先谈谈我对property的理解。
我们通常所说的property不是一个对象,它的表现形式主要有两种:
- 代表一个简单数据类型。
- 代表一个表现对象的指针(注意:这里说的是指针,而不是对象)。
2、atomic和nonatomic
- atomic为原子操作,是Objc使用的一种线程保护技术,基本上来讲,是防止在写未完成的时候被另外一个线程读取,造成数据错误。而这种机制是耗费系统资源的,所以在iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。
- nonatomic,非原子性访问,不加同步,多线程并发访问会提高性能。注意,如果不加此属性,则默认是两个访问方法都为原子型事务访问。
3、assign
assign是指针赋值,不对引用计数操作,使用之后如果没有置为nil,可能就会产生野指针。
4、weak
weak是弱引用(一般应用: UI控件,代理),类似于assign。对象销毁之后会自动置为nil,防止野指针。
5、retain(和strong类似)
释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1,用于指针变量。
就是说你定义了一个变量,然后这个变量在程序的运行过程中会被更改,并且影响到其他方法。(引用场景:类似于一条被牵着的狗,你用strong修饰一下,就相当于给这只狗又加了一条绳子,但是狗还是那条狗)。
6、copy
copy:指向的对象会被重新拷贝一遍(即会重新分配一个内存地址),并给这个新建的对象引用计数设置为1,通俗点的理解就是对象拷贝(引用场景:类似于重新创造了一只狗,并给这只狗套上了一条绳)。
四、assign,retain,weak,strong,copy 修饰
assign 和 weak:用于基础数据类型 (例如NSInteger)和C数据类型(int, float, double, char)另外还有 id 和 delegate(防止loop retain)。
retain 和 strong:用来修饰OC对象类型(NSArray、NSDate、NSNumber、模型类),一个对象只要有强指针引用着,就不会被销毁 ,也就是我们经常说的强引用。
copy:一般用在NSString*类型、block类型上。
copy只用于NSString而不能用于NSMutableString,如果当一个类继承NSObject,那么这个类里面的属性需要使用copy。
五、assign,retain,weak,strong,copy区别
1、retian和strong
xcode4.3及以后版本上面开发,retian和strong除了特殊的情况,其他都是一样的
在修饰block属性的时候,相信大家都知道要用copy吧,因为如果不copy的话,block是存放在栈连里面的,他的生命周期会随着函数的结束而出栈的,copy之后会放在堆里面。
strong在修饰block的时候就相当于copy,而retain修饰block的时候就相当于assign,这样block会出现提前被释放掉的危险。
2、assign 和 weak
两者都是弱引用,assign通常用于普通类型属性(如int,NSInteger),还有代理属性的修饰,基本上来说两者是可以通用的。
只是后者比前者多了一个功能,后者会在引用的对象被释放的时候将该属性置为nil,而前者依然会指向原来的位置,这样就会变成野指针。在oc中你给你一个nil对象发送消息不会crash,但是给一个对象发送他不能解析的消息是会crash的,所以总的来说weak要比assign安全一些。
像delegate属性建议用weak修饰而不是assign。
3、assign , copy,retain(strong)
- copy:只拷贝内容,不拷贝对象。用于希望保持一份传入值的拷贝,而不是值自身的情况,即把原来的对象完整的赋值到另外一地方,重新加载一内存区,一个地方变了不影响另一个地方的对象。
- assign:简单的直接赋值,相当于说两个对象指向同个内存区,一个地方的变了,其他的也跟着改变。
- retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1
例如:一个 NSString 对象,地址为 0×1111,内容为@”ABC”
Copy 到另外一个 NSString 之 后,地址为 0×2222,内容相同,新的对象 retain 为 1, 旧 有对象没有变化
retain 到另外一个 NSString 之 后,地址相同(建立一个指针,指针拷贝),内容当然相 同,这个对象的 retain 值+1
assign 地址还是0x1111,内容也还是“ABC”。
总的来说:
@property : 想长期拥有某个对象,应该用strong,其他对象用weak
其他基本数据类型依然用assign
两端互相引用时,一端用strong、一端用weak
注:具体使用说明可以查看下一篇转载的文章
参考:
assign和weak区别, retain和strong
IOS中assign、copy 、retain、strong、weak等关键字的含义
assign,weak,retain,strong,copy属性浅谈
iOS中assign与weak,retain与strong的区别