美文网首页
Swift 全局定时器管理类(单例模式)

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

作者: 小奉不在乎 | 来源:发表于2025-03-04 18:08 被阅读0次

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()
         }
     }
 }
 */

相关文章

  • Swift的单例模式及如何处理并发访问

    Swift的单例模式 Swift有两种方式实现单例模式 1、全局常量 2、类型常量 处理单例模式的并发访问 1、多...

  • 设计模式(Swift) - 单例模式、备忘录模式和策略模式

    设计模式(Swift) - 单例模式、备忘录模式和策略模式 设计模式(Swift) - 单例模式、备忘录模式和策略模式

  • swift struct 单例模式

    swift struct 单例模式

  • iOS-单例模式

    swift的单例设计模式 OC的单例设计模式 新学习一种单例思想

  • 单例

    内存中只有一个对象实例 提供一个全局访问点 OC中的单例 swift中的单例 swift改进过的单例

  • 单例模式

    单例模式 定义 保证一个类只有一个实例,并提供一个访问他的全局访问点 实现单例模式 全局变量不是单例模式 var ...

  • 单例模式

    前言 单例模式常用在一些全局唯一的管理类,避免对象重复创建,节省内存创建释放开销。 饿汉模式 每一次通过 new ...

  • 一行代码实现swift的单例模式

    swift实现单例的四种方式 : 单例模式 单例模式是设计模式中最简单的一种,甚至有些模式大师都不称其为模式,称其...

  • Swift单例模式

    Swift单例模式 单例模式 单例模式的作用是解决“应用中只有一个实例”的一类问题。在Cocoa Touch框架中...

  • 单例模式

    单例,全局只有一个实例 单例模式可以分为懒汉式和饿汉式: 懒汉式单例模式:在类加载时不初始化。 饿汉式单例模式:在...

网友评论

      本文标题:Swift 全局定时器管理类(单例模式)

      本文链接:https://www.haomeiwen.com/subject/sfnhmjtx.html