iOS中造成delloc不被调用的原因

最近在做需求的时候需要在键盘弹起的时候将一个半透明黑色蒙层覆盖在页面上,但是因为如果直接将这个蒙层添加到self.view中的话没办法覆盖到导航栏,所以我把它添加到了整个页面的最上方,覆盖到导航栏。

但是这样就有一个问题,就是当我pop出这个页面之后,这个蒙层并没有销毁,而是当我在其他页面弹出键盘的时候又显示了出来。有一个方法可以解决这个问题。就是在viewWillAppearviewWillDisappear中添加和移除。

1
2
3
4
5
6
7
8
9
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.view addSubView:self.maskView];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.maskView removeFromSuperView];
}

这样是可以解决问题,但是我在解决这个问题的过程中尝试着在dealloc中释放self.maskView时发现dealloc方法并没有被调用。事实上,页面已经被pop了,就应该调用dealloc方法才对。所以我们来看一下是什么会照成dealloc方法不被调用。

ViewController中有Block,并且照成了循环引用

仔细一看,我的代码中确实有使用了block,在里边也确实是使用了self.xxx,这样就照成了循环引用,一直有东西在指向self导致dealloc方法不被执行。

那么解决这个办法只需要添加__weak修饰自己本身即可。在MRC中要使用__block

1
__weak MyClass *weakSelf = self;

ViewController中有NSTimer,并且没有取消计时

如果你的页面中设置了NSTimer,那么在调用这个方法的时候

1
2
3
4
5
[NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(updateTime:)
userInfo:nil
repeats:YES];

你的目标targer设置为self,就增加了指向self的指针,如果这个NSTimer没有被取消,那么也不会调用dealloc

这时候只需要调用取消计时的方法就可以了。

1
[myTimer invalidate];

ViewController中使用了代理,并且是强引用

我们在使用代理的时候,最好需要把代理的属性设置为weak或是assign。如果你的代码中存在代理,那么去看一下他的属性是不是被设置成了retain或者是strong,这样也会让你的dealloc不被调用。

这时候只要把属性改为weakassign就可以及解决问题了。