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

如何在其他类的Label中自动更新Counter计数器的数值

问题根源

@ObservedObject是SwiftUI专属的属性包装器,仅能在SwiftUI视图中自动完成ObservableObject的变更订阅、触发UI刷新逻辑。在UIKit的UIViewController中使用时,它只是一个普通的强引用属性,不会自动监听@Published标记属性的变化,你仅在viewWillAppear中执行了一次Label赋值,后续counter值变化时自然不会同步更新UI。

修复方案

使用Combine框架手动订阅counter的变更事件,收到新值时在主线程更新Label即可,具体步骤如下:

  • 引入Combine框架
  • 给ViewController添加一个Set<AnyCancellable>类型的属性,用来持有订阅对象,避免订阅提前释放
  • 在viewDidLoad中绑定counter的发布者,收到新值时更新Label
  • 删除原来viewWillAppear中一次性给Label赋值的冗余代码

修改后的完整ViewController.swift代码:

import UIKit
import SwiftUI
import Combine // 新增引入Combine

class ViewController: UIViewController {
    
    @ObservedObject var stopWatch = StopWatch()
    @IBOutlet var label: UILabel!
    // 新增:持有订阅的集合
    private var cancellables = Set<AnyCancellable>()

    override func viewDidLoad() {
        super.viewDidLoad()
        // 订阅counter的数值变化
        stopWatch.$counter
            .receive(on: DispatchQueue.main) // 保证UI更新在主线程执行
            .sink { [weak self] currentCount in
                self?.label.text = "\(currentCount)"
            }
            .store(in: &cancellables)
    }

    @IBAction func start(_ sender: UIButton) { self.stopWatch.start() }
    @IBAction func stop(_ sender: UIButton) { self.stopWatch.stop() }
}

StopWatch.swift的代码不需要做任何修改,原有计时逻辑可正常运行。

补充说明:如果你不想引入Combine,也可以在StopWatch类中新增一个值变化回调闭包,每次counter变更时触发闭包,在ViewController中实现闭包逻辑更新Label,但用Combine和现有@Published逻辑配合是改造成本最低的方案。

内容的提问来源于stack exchange,提问作者dàhóngpáo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 18:06:32