造成循环引用的原因,就是两个及两个以上的对象相互强引用,无法释放。
一、block
一般情况下,我们使用copy修饰block,但copy的作用只是将block从栈区拷贝到堆区,并不是弱引用,而是强引用(copy修饰不可变对象时,相当于strong)。
所以self对block进行了强引用,那么block便不能强引用self。所以
解决方案
就是,在block中使用weakself
二、delegate
可以用weak修饰delegate。
三、NSTimer
1⃣️首先我们声明timer的时候,使用strong修饰的,self对timer进行的强引用,如下
@property (nonatomic, strong) NSTimer *timer;
2⃣️创建timer时,target对self又进行了强引用
- (NSTimer *)timer {
if (_timer == nil) {
_timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(setTime) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}
return _timer;
}
至此,循环引用已经形成。如果想控制器正常退出销毁,我们必须在退出之前销毁timer。
解决方案:在viewWillDisappear中销毁timer
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.timer invalidate];
self.timer = nil;
}
这样,控制器就可以正常退出了。
注意:如果我们没有将timer销毁,控制器也会执行dealloc方法,但是timer还会继续执行
四、通知
添加观察者和移除观察者,要成对出现。
如果只添加了观察者,没有移除观察者,会引起循环引用,导致控制器不能释放。
//添加观察者
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(changeCommunityAlert:) name:kHome_Module_changeCommunityAlert object:nil];
//移除观察者
[[NSNotificationCenter defaultCenter] removeObserver:self name:kHome_Module_changeCommunityAlert object:nil];