You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift 4如何设置Timer在每日指定时间(23:59)启动并重复执行?

如何让Timer在每日固定23:59启动并重复执行

我来帮你搞定这个问题!你已经找对了Timer重复执行的核心逻辑,现在只需要把首次触发的时间精准设置为下一个23:59的时刻就行,具体拆解如下:

1. 写个工具函数计算目标时间

我们需要借助Calendar和DateComponents来精准计算:如果当前时间还没到今天的23:59,就用今天的这个点;如果已经过了,就自动取明天的23:59。

func getNextFireDate(atHour hour: Int, minute: Int) -> Date {
    let calendar = Calendar.current
    // 获取当前日期的年、月、日、时、分组件
    var components = calendar.dateComponents([.year, .month, .day, .hour, .minute], from: Date())
    
    // 把时分设置为目标值(23:59)
    components.hour = hour
    components.minute = minute
    
    var nextFireDate = calendar.date(from: components)!
    
    // 如果目标时间已经过了今天,就往后推一天
    if nextFireDate < Date() {
        nextFireDate = calendar.date(byAdding: .day, value: 1, to: nextFireDate)!
    }
    
    return nextFireDate
}

2. 用目标时间初始化Timer

调用上面的函数拿到精准的首次触发时间,再传给Timer的fireAt参数就可以实现需求了:

// 获取下一个23:59的时间点
let targetDate = getNextFireDate(atHour: 23, minute: 59)

// 初始化Timer,每日重复执行
let timer = Timer(fireAt: targetDate, interval: 86400, target: self, selector: #selector(runCode), userInfo: nil, repeats: true)
RunLoop.main.add(timer, forMode: .commonModes)

// 你的定时执行方法
@objc func runCode() {
    print("定时任务执行啦!")
}

iOS 10+推荐写法(避免循环引用)

如果你是iOS 10及以上系统,更建议用block形式的Timer API,能规避target-action模式可能带来的循环引用问题:

let targetDate = getNextFireDate(atHour: 23, minute: 59)
let timer = Timer(fire: targetDate, interval: 86400, repeats: true) { [weak self] _ in
    self?.runCode()
}
RunLoop.main.add(timer, forMode: .commonModes)

小提醒

  • 当APP进入后台后,Timer大概率会暂停甚至失效,如果需要后台也能稳定执行任务,得结合iOS的BGTaskScheduler后台任务机制来处理,这是另一个独立的知识点啦。
  • 记得在合适的时机(比如页面销毁、APP退出时)调用timer.invalidate(),避免内存泄漏。

内容的提问来源于stack exchange,提问作者RJB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:51:56