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

如何在SwiftUI中编写CPU占用更低的高效TimerView计时器视图

计时器视图CPU占用过高优化方案

现有实现CPU高的核心原因

  • 刷新频率远高于实际显示需求:现有实现的刷新频率是60~100次/秒,如果你的计时器不需要精确到0.01秒级显示,所有高于显示精度的刷新都是无效计算,白白占用CPU
  • 资源未及时释放:全局Timer、未invalidate的CADisplayLink会在页面退出后仍持续运行,额外占用CPU
  • 字符串格式化效率低:直接调用time.description每次都会生成全量时间字符串,比按需格式化消耗更多CPU

优化方案

1. 按需调整刷新频率

根据你的显示精度设置刷新间隔:

  • 仅显示到秒:刷新间隔1s
  • 显示到0.1秒:刷新间隔0.1s
  • 仅需要毫秒级精度时才设置0.01s的刷新间隔

2. 优化计时器生命周期

计时器仅在页面可见时运行,页面消失后立即销毁释放

3. 复用格式化工具

全局复用DateFormatter/NumberFormatter,不要每次刷新都重新创建格式化对象

4. 增加调度容忍度

给Timer设置tolerance参数,允许系统小幅调整调度时机,合并唤醒降低CPU功耗

优化后代码示例

SwiftUI版本(显示到0.1秒,CPU占用可降至2%以下)

import SwiftUI

struct OptimizedTimerView: View {
    @State private var time: TimeInterval = 0
    @State private var timer: Cancellable?
    // 复用格式化逻辑
    private func formatTime(_ time: TimeInterval) -> String {
        String(format: "%.1f", time)
    }
    
    var body: some View {
        Text(formatTime(time))
            .onAppear {
                // 按需设置刷新间隔,这里用0.1s对应0.1秒的显示精度
                timer = Timer.publish(every: 0.1, tolerance: 0.01, on: .main, in: .common)
                    .autoconnect()
                    .sink { [weak self] date in
                        self?.time = date.timeIntervalSinceReferenceDate
                    }
            }
            .onDisappear {
                // 页面消失时销毁计时器
                timer?.cancel()
            }
    }
}

UIKit CADisplayLink版本

import UIKit

class OptimizedTimerViewController: UIViewController {
    @IBOutlet weak var timeLabel: UILabel!
    private var displayLink: CADisplayLink?
    // 全局复用格式化器
    private let numberFormatter: NumberFormatter = {
        let formatter = NumberFormatter()
        formatter.maximumFractionDigits = 1
        formatter.minimumFractionDigits = 1
        return formatter
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        displayLink = CADisplayLink(target: self, selector: #selector(updateTime))
        // 按需设置刷新率,30帧对应0.03秒左右精度,远高于0.1秒的显示需求
        if #available(iOS 15.0, *) {
            displayLink?.preferredFrameRateRange = .init(minimum: 10, maximum: 30)
        } else {
            displayLink?.preferredFramesPerSecond = 30
        }
        displayLink?.add(to: .main, forMode: .default)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        // 及时销毁displayLink避免内存泄漏和无效CPU占用
        displayLink?.invalidate()
        displayLink = nil
    }

    @objc private func updateTime() {
        guard let timestamp = displayLink?.targetTimestamp else { return }
        timeLabel.text = numberFormatter.string(from: NSNumber(value: timestamp))
    }
}

iOS15+ TimelineView优化版本

import SwiftUI

struct OptimizedTimelineTimerView: View {
    // 按需设置step,0.1s对应0.1秒的显示精度
    private let refreshStep = 0.1
    
    var body: some View {
        TimelineView(.periodic(from: .now, by: refreshStep)) { timeline in
            Text(String(format: "%.1f", timeline.date.timeIntervalSinceReferenceDate))
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 07:06:01