我們知道在iOS中Timer很容易引起引用循環(huán)谷羞。原因大家都很清楚就是Timer在運行后不僅會被當(dāng)前的target所引用,也會被runloop引用椰拒,timer本身依賴runloop來計時至扰。設(shè)置timer=nil都不行搔预。必須要調(diào)用Timer的invalidate()方法。在官方文檔中就闡述了invalidate()方法的作用
invalidate()
Stops the timer from ever firing again and requests its removal from its run loop.
使用timer還有一個需要注意的就是我們在程序中可能有很多地方都會使用到timer谆棱,但是timer又是非常耗資源的快压。所以我這里參考其他文章寫了一個timer的管理工具圆仔。主要就是對timer做一個全局的統(tǒng)一的管理。使用單例模式保證全局只有唯一的timer嗓节。這樣可以降低性能消耗方便管理荧缘。
代碼很簡單就兩個對象。
Task:當(dāng)前timer需要執(zhí)行任務(wù)的一個數(shù)據(jù)結(jié)構(gòu)
Timermanger: timer 的生成與方法的執(zhí)行拦宣,全局唯一的管理截粗。
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("執(zhí)行了")
}
TimerManger.share.runTask(task: taks)
使用Task保存了當(dāng)前循環(huán)任務(wù)需要執(zhí)行的任務(wù)與循環(huán)的時間。這里的時間是1/60秒來作為基礎(chǔ)的鸵隧。所以如果要設(shè)置1秒執(zhí)行一次那么interval需要設(shè)置為60绸罗。當(dāng)然這個timerManger很簡單有很多局限。只能在main線程執(zhí)行豆瘫。并且默認是common模式珊蟀。如果不滿足大家需求也可以隨便改。