如何在其他类的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
相关产品推荐
相关产品推荐

