Swift 全局定时器管理类(单例模式)

1. 订阅者专属间隔:

每个订阅者独立记录上次触发时间和间隔
使用字典存储订阅者信息,Key为自动生成的UUID

2.精准触发机制:

全局定时器以1秒为基准间隔进行轮询
使用abs(timeIntervalSince)确保设备休眠时的时间计算正确
每次触发检查所有订阅者的间隔是否满足

3.立即触发支持:

通过immediate参数控制首次是否立即执行
自动管理首次触发时间的基准设置

4. 线程安全优化:

使用带barrier的并发队列保证订阅者字典的线程安全
事件回调自动切换到主线程处理UI操作

5. 内存管理:

结合Combine的AnyCancellable自动管理订阅生命周期
对象释放时自动取消订阅

import Foundation
import Combine

/// 全局定时器管理类(单例模式)
final class GlobalTimerManager {
    
    // MARK: - 单例实例
    static let shared = GlobalTimerManager()
    
    // MARK: - 内部类型
    private struct Subscriber {
        let handler: (Date) -> Void
        let interval: TimeInterval
        var lastTriggerTime: Date?
    }
    
    // MARK: - 私有属性
    private var timer: DispatchSourceTimer?
    private var subscribers = [UUID: Subscriber]()
    private let queue = DispatchQueue(
        label: "com.globaltimer.manager",
        attributes: .concurrent
    )
    private let timerQueue = DispatchQueue(
        label: "com.globaltimer.timer",
        qos: .utility
    )
    
    // MARK: - 定时器控制
    /// 启动全局定时器(固定1秒间隔)
    func start() {
        queue.async(flags: .barrier) { [weak self] in
            guard let self = self, self.timer == nil else { return }
            
            let timer = DispatchSource.makeTimerSource(queue: self.timerQueue)
            
            // 使用wall time保证设备休眠后的准确性
            timer.schedule(
                wallDeadline: .now(),
                repeating: 1.0,
                leeway: .milliseconds(50)
            )
            timer.setEventHandler { [weak self] in
                self?.handleTimerTrigger()
            }
            
            timer.resume()
            self.timer = timer
        }
    }
    
    /// 停止定时器
    func stop() {
        queue.async(flags: .barrier) { [weak self] in
            guard let self = self, let timer = self.timer else { return }
            timer.cancel()
            self.timer = nil
            self.subscribers.removeAll()
        }
    }
    
    // MARK: - 订阅管理
    /// 订阅定时事件(默认不立即触发)
    func subscribe(
        interval: TimeInterval,
        immediate: Bool = false,
        _ handler: @escaping (Date) -> Void
    ) -> AnyCancellable {
        let uuid = UUID()
        let currentDate = Date()
        
        // 初始化触发时间
        var lastTriggerTime: Date?
        if immediate {
            // 立即触发并设置下次触发时间
            DispatchQueue.main.async { handler(currentDate) }
            lastTriggerTime = currentDate
        } else {
            // 设置初始触发基准时间
            lastTriggerTime = currentDate
        }
        
        let subscriber = Subscriber(
            handler: handler,
            interval: interval,
            lastTriggerTime: lastTriggerTime
        )
        
        queue.async(flags: .barrier) { [weak self] in
            self?.subscribers[uuid] = subscriber
        }
        
        return AnyCancellable { [weak self] in
            self?.unsubscribe(uuid: uuid)
        }
    }
    
    // MARK: - 私有方法
    private func handleTimerTrigger() {
        let currentDate = Date()
        printLog("全局定时器-主:\(currentDate)")
        queue.sync { [weak self] in
            guard let self = self else { return }
            
            for (uuid, var subscriber) in self.subscribers {
                guard let lastTime = subscriber.lastTriggerTime else {
                    continue
                }
                
                // 计算时间差(绝对值确保设备休眠后的正确性)
                let elapsed = abs(currentDate.timeIntervalSince(lastTime))
                if elapsed >= subscriber.interval {
                    // 主线程执行回调
                    DispatchQueue.main.async {
                        subscriber.handler(currentDate)
                    }
                    // 更新触发时间
                    subscriber.lastTriggerTime = currentDate
                    self.subscribers[uuid] = subscriber
                }
            }
        }
    }
    
    private func unsubscribe(uuid: UUID) {
        queue.async(flags: .barrier) { [weak self] in
            self?.subscribers.removeValue(forKey: uuid)
        }
    }
}
// 使用示例
/**
 // 启动定时器(App启动时调用)
 GlobalTimerManager.shared.start()

 // 在需要的地方订阅事件
 class DataService {
     private var cancellables = Set<AnyCancellable>()
     
     init() {
         // 订阅30秒间隔(不立即触发)
         GlobalTimerManager.shared.subscribe(interval: 30) { [weak self] date in
             self?.refreshData()
         }.store(in: &cancellables)
     }
     
     private func refreshData() {
         print("正在执行数据刷新...")
     }
 }

 // 复杂间隔组合示例
 class AnalyticsManager {
     init() {
         // 每分钟上报
         GlobalTimerManager.shared.subscribe(interval: 60) { _ in
             self.reportAnalytics()
         }
         
         // 每5秒检查一次网络状态
         GlobalTimerManager.shared.subscribe(interval: 5) { _ in
             self.checkNetworkStatus()
         }
     }
 }
 */

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容