- 日常开发中,使用到定时器都需要手动去释放,不仅麻烦还容易出错,所以现在我们来设计一个可以自动释放的定时器。
现在开始
- 以下是定时器(
Timer
)创建的一个常用方法,下面我们就根据这个方法来设计可以自动释放的定时器。
open class func scheduledTimer(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool) -> Timer
1.自动释放的假想
- 当每次执行
selector
方法的时候,我们就判断定时器的持有者taeget
是否存在,如果不存在,则销毁定时器。 - 在定时器中,我们无法判断
target
是否存在,所以我们就创建一个中介target
,保存原来的target
,在这个中介target
做一个判断的逻辑。
2.中介Target
typealias TimerBlock = () -> Swift.Void
class TimerTarget: NSObject {
weak var target: AnyObject?
var timer: Timer?
var name: String?
var block: TimerBlock?
/// 初始化
init(target aTarget: AnyObject?, name aName: String?, block aBlock: TimerBlock?)
{
target = aTarget as AnyObject
name = aName
block = aBlock
}
convenience override init() {
self.init(target: nil, name: nil, block: nil)
}
@objc func aiewing()
{
guard let _ = self.target,
let block = self.block else {
self.timer?.invalidate()
self.timer = nil
guard let name = self.name else {
return
}
print("Timer called \(name) has been invalidated")
return
}
// 执行block
block()
}
}
-
这个
中介target
最主要需要保存3个变量。-
target
:这个是自动释放的关键所在,修饰词一定要使用weak
,修饰词一定要使用weak
,修饰词一定要使用weak
,不然会造成循环引用,导致定时器依旧不能自动释放。 -
timer
:这个定时器创建的实例变量,需要使用它控制定时器逻辑。 -
block
:这个block
是用来响应外部定时器执行的方法的,所以也是需要的。
-
-
在方法
aiewing()
中,我们先判断target
是否存在,如果存在就执行block
,如果不存在就释放定时器。
3.Timer类扩展
extension Timer
{
class func scheduledTimerAutoToRelease(timeInterval ti: TimeInterval, target aTarget: AnyObject, name aName: String, userInfo aUserInfo: Any?, repeats yesOrNo: Bool, block aBlock: @escaping TimerBlock) -> Timer
{
let timerTarget: TimerTarget = TimerTarget(target: aTarget, name: aName, block: aBlock)
let timer: Timer = Timer.scheduledTimer(timeInterval: ti, target: timerTarget, selector: #selector(timerTarget.aiewing), userInfo: aUserInfo, repeats: yesOrNo)
timerTarget.timer = timer
return timer
}
}
- 先创建一个
中介target
,然后把中介target
作为定时器的持有者,最后把定时器实例传递到中介target
。
结束
- 以上就是一个简单可以自动释放的定时器Demo。
- 谢谢阅读
网友评论