下边是一个定时器的创建方法:
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
target:The object to which to send the message specified by aSelector when the timer fires. The timer maintains a strong reference to this object until it (the timer) is invalidated.
target:定时器会强引用target直到定时器终止。
因此现在很明确了,如果把定时器申明成了target的属性,那将必然引起循环引用。这个有分为两种情况:
情况一:target是ViewController
这时候我们要想不造成循环引用,解决方案是在viewWillDisappear的关闭定时器。
情况二:target为我们封装的空间
如果target是我们自己封装的控件,那怎么办呢?如果我们依然在viewWillDisappear里边停掉定时器的话岂不是破坏了这个控件的封装性。如果这个控件交给别人使用的话,还得让别人注意要在viewWillDisappear中停掉定时器。
苹果提供了一个方法:
- (void)willMoveToSuperview:(nullable UIView *)newSuperview;
Tells the view that its superview is about to change to the specified superview.
The default implementation of this method does nothing. Subclasses can override it to perform additional actions whenever the superview changes.
告诉子视图它现在的父视图准备把它移动到特定的视图上。默认这个方法的实现是什么也不做。子视图可以重写来执行额外的方法无论父视图什么时候改变。