影响控制器正常释放的常见问题

http://www.jianshu.com/p/bcc0bcaadd6c

导致控制器不能正常释放的原因?

控制器的引用计数不为0,也就是说被其他对象强引用,因此不能正常释放。

如何知道控制器是否已经正常释放?

在ARC模式下,控制器在彻底销毁之前会调用dealloc方法,并自动调用[super dealloc]方法。因此,可以重写基类的dealloc方法,输出控制器销毁提示信息,如果控制器没有调用dealloc方法,说明不能正常释放。

-(void)dealloc {

NSLog(@"%@dealloc",NSStringFromClass([self class]));

}

问题一:block引发的循环引用

无弱引用声明的情况下,block持有它里面所有对象的所有权,即为强引用,所以当在block里面使用self的时候,可能会导致控制器不能正常释放。

比如:objectB拥有callbackBlock属性,在objectA中设置该属性

[objectBsetCallbackBlock:^{

[self excuBlock];

}];

在block中引用了自身方法(或变量),形成了循环引用。

解决方法:

在block中使用对自身对象的弱引用来替换self

__weak typeof(self)  weakSelf = self;

[objectB setCallbackBlock:^{

[weakSelf excuBlock];

}];

如果在block使用了成员变量,也要使用其弱引用,以_dataSource为例:

__weak typeof(_dataSource) weakDataSource = _dataSource;

问题二:强引用的delegate引发的循环引用

如果一个delegate属性的声明是strong的时候,会持有自身控制器的所有权,导致控制器不能正常释放。

比如:

CustomView的delegate声明

@property

(nonatomic, strong) id delegate;

在控制器中赋值

self.customView.delegate

= self;

这样,造成self对customView强引用,customView对self强引用,引发循环引用。

解决方法:

对代理使用弱引用

@property

(nonatomic, weak) id delegate;

问题三:使用了NSTimer没有销毁

只有无限重复的定时器才会导致控制器无法销毁

当我们使用NSTimer的方法

self.timer= [NSTimer scheduledTimerWithTimeInterval:1.0 target:selfselector:@selector(timerAction) userInfo:nil repeats:YES];

[[NSRunLoop mainRunLoop]addTimer:self.timer forMode:NSRunLoopCommonModes];

时,定时器对象会对它的target(即self:当前控制器)持有强引用,如果定时器不销毁,则控制器无法释放。

解决方法:

在-(void)viewWillDisappear:(BOOL)animated或者-

(void)viewDidDisappear:(BOOL)animated或者其他确定离开当前控制器的方法中销毁定时器。

-(void)viewDidDisappear:(BOOL)animated {

[super viewDidDisappear:animated];

if (self.timer != nil) {

[self.timer invalidate];

self.timer = nil;

}

}

你可能感兴趣的:(影响控制器正常释放的常见问题)