iOS swift timer管理

2022-04-15  本文已影响0人  蜗牛炒饭

我们知道在iOS中Timer很容易引起引用循环。原因大家都很清楚就是Timer在运行后不仅会被当前的target所引用,也会被runloop引用,timer本身依赖runloop来计时。设置timer=nil都不行。必须要调用Timer的invalidate()方法。在官方文档中就阐述了invalidate()方法的作用

invalidate()
Stops the timer from ever firing again and requests its removal from its run loop.

使用timer还有一个需要注意的就是我们在程序中可能有很多地方都会使用到timer,但是timer又是非常耗资源的。所以我这里参考其他文章写了一个timer的管理工具。主要就是对timer做一个全局的统一的管理。使用单例模式保证全局只有唯一的timer。这样可以降低性能消耗方便管理。
代码很简单就两个对象。
Task:当前timer需要执行任务的一个数据结构
Timermanger: timer 的生成与方法的执行,全局唯一的管理。

struct Task {
    var taskId: String = ""
    var interval: Int
    var event: () -> ()
}

class TimerManger: NSObject {
    static let share = TimerManger()

    override private init() {
        super.init()
        RunLoop.main.add(self.timer, forMode: .common)
    }

    private var taskArr = [Task]()

    private lazy var timer: Timer = {
        var index = 0
        let timer = Timer.scheduledTimer(withTimeInterval: 1 / 60, repeats: true) { _ in
            if index == 59 {
                index = 0
            }
            for task in self.taskArr {
                if index % task.interval == 0 {
                    task.event()
                }
            }
            index += 1
        }
        return timer
    }()

    func runTask(task: Task) {
        for t in self.taskArr {
            if t.taskId == task.taskId {
                return
            }
        }
        self.taskArr.append(task)
    }

    func cancelTaskWithId(_ id: String) {
        for i in 0 ..< self.taskArr.count {
            if self.taskArr[i].taskId == id {
                self.taskArr.remove(at: i)
            }
        }
    }
}

使用也很简单

let taks = Task.init(taskId: "aa", interval: 60) {
      print("执行了")
 }
TimerManger.share.runTask(task: taks)

使用Task保存了当前循环任务需要执行的任务与循环的时间。这里的时间是1/60秒来作为基础的。所以如果要设置1秒执行一次那么interval需要设置为60。当然这个timerManger很简单有很多局限。只能在main线程执行。并且默认是common模式。如果不满足大家需求也可以随便改。

上一篇 下一篇

猜你喜欢

热点阅读