问题:
在做视频播放的时候,重写viewController
的dealloc()
,想要销毁视频播放的player
,但是发现并没有成功调用dealloc()
Reason:
控制器在被pop后移出栈后会被释放,但有些时候会发现控制器出栈的时候不会调用dealloc方法,是因为当前控制器被某个对象强引用了,控制器的引用计数不为0
,系统无法帮你释放这部分内存
。原因大致有以下几点:
1. 控制器中NSTimer
没有被销毁
当viewController
中存在NSTime
r时,需要特别注意,当调用
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTime:) userInfo:nil repeats:YES]
时,因为target:self
,也就是引用了当前viewController
,导致控制器的引用计数加1,如果没有将这个NSTimer
销毁,它将一直保留该viewController
,无法释放,也就不会调用dealloc方法。所以,需要在viewWillDisappear
之前需要把控制器用到的NSTimer
销毁。
[timer invalidate]; // 销毁timer
timer = nil; // 置nil
2. viewController
中的代理不是weak
属性
例如@property (nonatomic, weak) id delegate;
代理要使用弱引用,因为自定义控件是加载在视图控制器中的,视图控制器view
对自定义控件是强引用,如果代理属性设置为strong
,则意味着delegate
对视图控制器也进行了强引用,会造成循环引用。导致控制器无法被释放,最终导致内存泄漏。
3. viewController
中block
的循环引用
在ARC
下,block
会把它里面的所有对象强引用,包括当前控制器self
,因此有可能会出现循环引用的问题。比如viewController
中有个block
属性,在block
中又强引用了self
或者其他成员变量,那么这个viewController
与自己的block
属性就形成循环引用,导致viewController
无法释放。(我遇到的就是这个问题)
// ARC enabled
/************** MyObject Class **************/
typedefvoid(^myBlock)(void);
@interfaceMyObject:NSObject
{
myBlock blk;
}
@end
@implementationMyObject
- (id)init
{
self=[superinit];
blk = ^{
NSLog(@"self = %@",self);
};
returnself;
}
- (void)dealloc
{
NSLog(@"dealloc");
}
@end
/************** main function **************/
int main()
{
id myObject=[[MyObjectalloc] init];
NSLog(@"%@",myObject);
return 0;
}
由于self
是__strong
修饰,在 ARC
下,当编译器自动将代码中的 block
从栈拷贝到堆时,block
会强引用和持有self
,而self
恰好也强引用和持有了 block
,就造成了传说中的循环引用。