- 本文乃己之拙见,欢迎指正,转载请注明出处。
进入正题之前先了解两个概念:
-
悬空指针:它曾经指向一个有效地址,但是现在不再指向有效地址(个人添加,其实就是原来的那块地址不能通过这个指针去访问了)。这通常是因为指针所指的内存单位被释放了并且不再有效了。空悬指针存在并没有什么问题,除非你尝试通过这个指针访问指向的地址空间。不遗留任何悬空指针总是最好的实践方式。
-
野指针:它指向一个已删除的对象或未申请访问受限内存区域的指针。具体产生野指针的原因有很多种,查“百度百科”,看了野指针产生的原因之后,就会理解野指针和悬空指针还是有一定的区别的。
我们先谈谈assign和weak
-
assign:诞生于MRC,assign是指针赋值,不对引用计数操作,使用之后如果没有置为nil,可能就会产生悬空指针。一般是对C基本数据类型成员变量的声明,适用于基本数据类型如int,float,struct等,当然也可以用在对象类型成员变量上,只是其代表的意义只是单纯的指针赋值。举例如果把对象A的指针赋值给assign声明的成员变量B,则B只是简单地保存此指针的值,且并不持有对象A,也就意味着如果A被销毁,则B就指向了一个已经被销毁的对象,如果再对其发送消息会引发崩溃。
-
weak:诞生于ARC,weak表示的是一个弱引用,这个引用不会增加对象的引用计数,并且在所指向的对象被释放之后,weak指针会被置为nil。避免悬空指针可能产生崩溃的问题。weak引用通常是用于处理循环引用的问题。关于weak底层的详细实现可参考这篇文章http://www.cocoachina.com/ios/20150605/11990.html
-
为什么ARC下修饰代理用assign会崩溃?
- 因为当assign修饰的对象释放后,指针不会自动被置为nil,之后再向该对象发消息会崩溃。
- 总结:weak和assign都不会影响引用计数,它们修饰的类型也有不同。weak指针在对象释放后会被置为nil,更安全一些。
再说说weak和strong
- weak是弱引用,strong是强引用。举个比较容易理解的例子来加深对它们的理解:
-
想象我们的对象是一条狗,狗想要跑掉(引用计数为0时被释放)
-
一个strong型指针就像是一根牵绳使拴住狗(引用计数+1),只要你用牵绳拴住狗,狗就不会跑掉。如果有2个人牵着一条狗(2个strong型指针指向1个对象,引用计数为2),除非2根牵绳都脱落 ,引用计数变为0,否着狗是不会跑掉
-
weak型指针不会影响引用计数,就像是一个小孩指着狗喊到:“看!一只狗在那” ,(weak指针)会一直指向它,让小孩只能看到狗而不能牵着狗。只要狗的牵绳脱落,狗就会跑掉小孩也就看不见了,和多少个小孩在看着狗无关。也就是说当最后一个strong型指针不再指向对象,那么对象就会被释放,同时所有的weak型指针都将会被清除
- 总结:一旦最后一个指向该对象的所有strong类型的指针离开,这个对象将被释放,如果这个时候还有weak指针指向该对象,则会清除掉所有剩余的weak指针。
-
补充一个知识点:
- retain,copy,new,alloc会增加引用计数,还有addsubview、push也会增加,因为view会有一个栈(subviews),addsubview就是将subview加入这个栈,当然会增加。为什么push会增加,那是因为navcontroller有一个栈(viewcontrollers),push就是加入这个栈,当然会增加。
-
为什么在ARC下修饰delegate要用weak而不是strong?
- 用tableview的代理(viewcontroller)例子来解释:
- 如果tableview用strong强引用了其代理viewcontroller,viewcontroller又strong强引用了tableview,就造成了循环引用,谁都不能被释放,会造成内存泄漏。用weak使tableview弱引用viewcontroller,不会造成循环引用。
-
手动创建控件时,什么时候将控件声明成strong,什么时候将控件声明成weak?
具体分析可以参考一下我的另一篇文章--《对手动创建控件时weak&strong的探究》
http://www.jianshu.com/p/73f29071ab8a -
为什么我们从xib或storyboard中引用到控制器的属性都是weak型指针?
- 在控件放在view上的时候,已经形成了如下的引用关系,以UIButton为例:
UIViewController->UIView->subView->UIButton - 为这个UIButton声明一个weak属性
@property(nonatomic,weak) IBOOutlet UIButton *btn;
- 在控件放在view上的时候,已经形成了如下的引用关系,以UIButton为例:
- xib/storyboard的subViews对这个Button是强引用,你声明的属性btn是弱引用,其引用计数为1。该对象不会被自动释放,会在UIViewController被释放的时候释放。
6.用strong,retain,copy修饰的属性对象,调用其set方法可使引用计数+1,编译器隐藏了retain等代码。
网友评论