160 lines
6.3 KiB
Swift
160 lines
6.3 KiB
Swift
//
|
||
// GCDTimer.swift
|
||
// DDTimerSwiftKit_Private
|
||
// Created by DDIsFriend on 2023/9/15.
|
||
|
||
|
||
import Foundation
|
||
import DDLogKit_Private
|
||
|
||
public let GCDT = GCDTimer.default
|
||
open class GCDTimer {
|
||
public static let `default` = GCDTimer()
|
||
|
||
private var timerSources : [GCDTimerAbstract] = []
|
||
|
||
public var canceledCompletionHandler:(() -> Void)? // 主动取消定时器时,由于定时器当前可能存在任务,所以要等任务结束后再进行相应的操作
|
||
|
||
/// 取消定时器时,定时器如果有正在执行的任务,会先将当前正在执行的任务执行完成才会取消成功,因此如果需要添加相同名字的定时器,需要确保之前同名的定时器已经被彻底取消了。
|
||
/// - Parameters:
|
||
/// - named: 定时器名字
|
||
/// - delay: 定时器延迟多久开始执行第一次操作
|
||
/// - repeating: 定时器间隔时间
|
||
/// - repeatCount: 重复次数
|
||
/// - repeatHandler: 定时器操作
|
||
/// - cancelHandler: 如果执行了cancelHandler,就不会执行completionHandler
|
||
/// - completionHandler: 如果执行了completionHandler,就不会执行cancelHandler
|
||
public func addGCDTimer(named timerName:String,delay:DispatchTimeInterval,repeating:DispatchTimeInterval,repeatCount:Int = Int.max,repeatHandler:@escaping (() -> Void),cancelHandler:(() -> Void)? = nil,completionHandler:(() -> Void)? = nil) {
|
||
if let _ = timerSources.first(where: { gcdTimerA in
|
||
gcdTimerA.timerName == timerName
|
||
}) {
|
||
DDLog(message: "定时器\'\(timerName)\'重复添加,添加失败")
|
||
return
|
||
}
|
||
|
||
let gcdTimerA = GCDTimerAbstract(named: timerName)
|
||
gcdTimerA.addGCDTimer(delay: delay, repeating: repeating, repeatCount: repeatCount) {
|
||
repeatHandler()
|
||
} cancelHandler: {[weak self] timerName in
|
||
// 移除定时器
|
||
self?.removeGCDTimer(named: timerName)
|
||
// 添加定时器处执行取消操作
|
||
if let cancelHandler {
|
||
cancelHandler()
|
||
}
|
||
// 取消定时器处执行取消操作
|
||
if let canceledCompletionHandler = self?.canceledCompletionHandler {
|
||
canceledCompletionHandler()
|
||
}
|
||
} completionHandler: {[weak self] timerName in
|
||
// 移除定时器
|
||
self?.removeGCDTimer(named: timerName)
|
||
// 执行结束操作
|
||
if let completionHandler {
|
||
completionHandler()
|
||
}
|
||
}
|
||
|
||
timerSources.append(gcdTimerA)
|
||
DDLog(message: "定时器\'\(timerName)\'添加成功")
|
||
// 打印剩余的定时器
|
||
logTimerName()
|
||
}
|
||
|
||
|
||
/// 在取消定时器时,假如定时器正在执行任务,这个过程中被多次取消且携带了canceledCompletionHandler,只会执行最后一次赋值的canceledCompletionHandler。
|
||
/// - Parameters:
|
||
/// - timerName: 定时器名字
|
||
/// - canceledCompletionHandler: 取消定时器后的操作
|
||
public func cancelGCDTimer(named timerName:String,canceledCompletionHandler:(() -> Void)? = nil) {
|
||
// 当timerSources中包含定时器时,取消定时器
|
||
if let gcdTimerA = timerSources.first(where: { gcdTimerA in
|
||
gcdTimerA.timerName == timerName
|
||
}) {
|
||
self.canceledCompletionHandler = canceledCompletionHandler
|
||
gcdTimerA.cancelGCDTimer(isCanceledManually: true)
|
||
}else{
|
||
DDLog(message: "定时器\'\(timerName)\'取消失败,未包含")
|
||
}
|
||
}
|
||
|
||
public func containsGCDTimer(named timerName:String) -> Bool {
|
||
if let _ = timerSources.first(where: { gcdTimerA in
|
||
gcdTimerA.timerName == timerName
|
||
}) {
|
||
return true
|
||
}
|
||
return false
|
||
}
|
||
|
||
func removeGCDTimer(named timerName:String) {
|
||
// 移除定时器的抽象类
|
||
timerSources.removeAll { gcdTimerA in
|
||
gcdTimerA.timerName == timerName
|
||
}
|
||
DDLog(message: "定时器\'\(timerName)\'移除成功")
|
||
// 打印剩余的定时器
|
||
logTimerName()
|
||
}
|
||
|
||
func logTimerName() {
|
||
for gcdTimerA in timerSources {
|
||
DDLog(message:("剩余定时器:\'\( gcdTimerA.timerName)\'"))
|
||
}
|
||
}
|
||
}
|
||
|
||
class GCDTimerAbstract {
|
||
|
||
private let timerSource = DispatchSource.makeTimerSource(flags: .strict,queue: dispatch_queue_concurrent_t(label: "GCDTimerConcurrentQueue"))
|
||
|
||
public var timerName : String
|
||
|
||
public var isCanceledManually : Bool = false // 是否时主动取消定时器
|
||
|
||
init(named timerName: String) {
|
||
self.timerName = timerName
|
||
}
|
||
|
||
public func addGCDTimer(delay:DispatchTimeInterval,repeating:DispatchTimeInterval,repeatCount:Int,repeatHandler:@escaping (() -> Void),cancelHandler:((String) -> Void)? = nil,completionHandler: ((String) -> Void)? = nil) {
|
||
// 当前剩余的次数
|
||
var leftRepeatCount = repeatCount
|
||
|
||
timerSource.setEventHandler(handler: {[weak self] in
|
||
// 定时器执行的任务
|
||
repeatHandler()
|
||
|
||
leftRepeatCount-=1
|
||
// 此时定时器次数结束
|
||
if (leftRepeatCount > 0) == false {
|
||
self?.cancelGCDTimer(isCanceledManually: false)
|
||
}
|
||
})
|
||
|
||
timerSource.setCancelHandler(handler: {[weak self] in
|
||
if self?.isCanceledManually == true {
|
||
// 定时器中途被取消时,在添加定时器的位置需要执行的取消操作
|
||
if let cancelHandler,let timerName = self?.timerName {
|
||
cancelHandler(timerName)
|
||
}
|
||
|
||
// 定时器中途被取消时,在取消完成后
|
||
}else{
|
||
// 定时器结束后执行
|
||
if let completionHandler,let timerName = self?.timerName {
|
||
completionHandler(timerName)
|
||
}
|
||
}
|
||
})
|
||
|
||
timerSource.schedule(wallDeadline: DispatchWallTime.now() + delay,repeating: repeating)
|
||
timerSource.activate()
|
||
}
|
||
|
||
// 次数统一处理结束,因为会有cancelHander
|
||
public func cancelGCDTimer(isCanceledManually:Bool) {
|
||
self.isCanceledManually = isCanceledManually
|
||
timerSource.cancel()
|
||
}
|
||
}
|