ARC 工程是可以重写 dealloc 方法并被系统调用的,但不需要手动调用父类的 dealloc ,手写[super dealloc]方法会报错,事实上系统会自动帮你调用父类的 dealloc 方法,不需要你实现。可以通过在 dealloc 方法中打印 log 查看控制器是否被释放。
控制器在被 pop 后移出栈后会被释放,但有些时候会发现控制器出栈的时候不会调用 dealloc 方法,归根结底,是因为当前控制器被某个对象强引用了,控制器的引用计数不为 0 ,系统无法帮你释放这部分内存。
<!--more-->
当控制器中存在 NSTimer 时,就需要注意,因为当[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTime:) userInfo:nil repeats:YES];时,这个 /target:self/ 就增加了 VC 的 RetarnCountr, 如果你不将这个 timer invalidate ,就别想调用 dealloc 。需要在 viewWillDisappear 之前需要把控制器用到的 NSTimer 销毁。
例如@property (nonatomic, weak) id<HCAppViewDelegate> delegate;代理要使用弱引用,因为自定义控件是加载在视图控制器中的,视图控制器 view 对自定义控件是强引用,
如果代理属性设置为 strong ,则意味着 delegate 对视图控制器也进行了强引用,会造成循环引用。导致控制器无法被释放,最终导致内存泄漏。
block 会把它里面的所有对象强引用(在 ARC 下)/PS:MRC 下会 retain 加 1/,包括当前控制器 self ,因此有可能会出现循环引用的问题。
即一个对象有一个 Block 属性,然而这个 Block 属性中又引用了对象的其他成员变量,那么就会对这个变量本身产生强应用,那么这个对象本身和他自己的 Block 属性就形成了循环引用。在 ARC 下需要修改成这样:(/也就是生成一个对自身对象的弱引用/)
即:保险起见 block 中所有的涉及到 self 的全给替换成 weakSelf
其实总结下来也就是:控制器强引用着 block 。凡是控制器的对象,或者控制器的成员变量,只要在 block 中就会被强引用,(间接导致 block 强引用了控制器)。引发循环引用,最终导致内存泄漏!
系统自带的动画的 block 方法、 dispathafter()等方法,可以不用_weak typeof (self)weakSelf = self;
1
chisj 2015-10-15 09:59:13 +08:00 1
关于 循环引用:
1 :不是所有 block 的 self 都要替换成 weakSelf ,被 controller 本身 retain 的 block (或者 block 的 copy )才需要引用 weakSelf 。 2 :不仅仅是 self , A 对象 retain 了 block , block 又 retain 了 A ,则 A 也会被循环引用,同理,可用 weakA 解决。 所以:保险起见 block 中所有的涉及到 self 的全给替换成 weakSelf ->是不必要的做法,也是不明就里的做法,关注的点不应该是所有 block ,也不是 self 本身,而是两个相互 retain 的对象。 祝玩得愉快^_^ |
2
stormxx 2015-10-15 10:23:13 +08:00 via iPhone
不错!顶一下~
|
3
zhanghaitao 2015-10-15 11:20:59 +08:00
真心不错的
|
4
finab 2015-10-15 11:26:29 +08:00 1
@chisj good~
不过对于新手来说,很难分辨需不需要 weak 。 所以只要是 block 里都用 weak ,事实上是有帮助的, 而新手做的功能,需要在 block 里 weak 的,基本都是 就算在用之前被释放了,也没关系的那种对象 比如 controller |
5
chisj 2015-10-15 12:16:03 +08:00
@finab 对于新手来说,也是要区分是否需要 weak :一个是某些情况下用 weak 确实会有问题,虽然新手不容易碰到;另一个是,如果养成了还没理清原理就敢写下代码的习惯,其实对新手的成长之路不太好。
内存管理是一道不高不低的坎,如果刚开始就有意去躲避这些坎,而不是啃下这块骨头,虽然当时轻松,后面会浪费更多的精力去补。 |
6
loveuqian 2015-10-15 15:01:31 +08:00 via iPhone
手机 mark
感谢总结 |
7
tunnyios OP 其实总结下来也就是:控制器强引用着 block 。凡是控制器的对象,或者控制器的成员变量,只要在 block 中就会被强引用,(间接导致 block 强引用了控制器)。引发循环引用,最终导致内存泄漏
|
8
MeiganFang 2015-10-15 17:10:24 +08:00 1
将 block 中所有的涉及到 self 的全给替换成 weakSelf ,并不是完全之策。比如多线程情况下, block 涉及到的 self 会多次 retain -1 ,这种情况会导致 block 未执行完 self 就已经释放。典型按理 AFNetworking
__weak __typeof(self)weakSelf = self; AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) { __strong __typeof(weakSelf)strongSelf = weakSelf; strongSelf.networkReachabilityStatus = status; if (strongSelf.networkReachabilityStatusBlock) { strongSelf.networkReachabilityStatusBlock(status); } }; 解决引用循环问题,是初级工程师到中级工程师必经的技术点。 |
9
aaronlam 2015-10-16 00:53:22 +08:00 via iPad
总结的很赞 ⊙▽⊙
|
10
WildCat 2015-10-16 19:33:11 +08:00
@MeiganFang
AFN Block 的行为,在 Swift 中是否还是自动 -1 ? 另外再 Swift 的 Alamofire 中是否还是自动 -1 ? 我 Swift 里习惯用 [weak self] ,目前还没注意到 ViewController 提前释放的问题(初学者) |