一个可以自动释放的定时器(Timer)

  • 日常开发中,使用到定时器都需要手动去释放,不仅麻烦还容易出错,所以现在我们来设计一个可以自动释放的定时器。

现在开始

  • 以下是定时器(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个变量。

    1. target:这个是自动释放的关键所在,修饰词一定要使用weak,修饰词一定要使用weak,修饰词一定要使用weak,不然会造成循环引用,导致定时器依旧不能自动释放。
    2. timer:这个定时器创建的实例变量,需要使用它控制定时器逻辑。
    3. 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。
  • 谢谢阅读

你可能感兴趣的:(一个可以自动释放的定时器(Timer))