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

如何监听@Published变量变化并刷新UIKit的UITableView?

解决方法

因为UIKit无法像SwiftUI那样自动响应@Published属性的变化,所以需要手动监听ViewModel的profiles数组更新,以此触发UITableView的刷新,具体配置如下:

  1. 在UIKit视图控制器中订阅ViewModel的profiles变化
    给视图控制器添加AnyCancellable类型的属性存储订阅对象,防止其被提前释放。在viewDidLoad中通过Combine框架订阅viewModel.$profiles的变化,收到更新通知时调用tableView.reloadData()。
    示例代码:

    import Combine
    
    class ProfilesViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
        @ObservedObject var viewModel: ProfilesViewModel
        private var cancellables = Set<AnyCancellable>()
        private var tableView = UITableView()
    
        init(viewModel: ProfilesViewModel) {
            self.viewModel = viewModel
            super.init(nibName: nil, bundle: nil)
        }
    
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // 省略tableView初始化与配置代码
            
            // 订阅profiles数组的更新
            viewModel.$profiles
                .receive(on: DispatchQueue.main) // 确保在主线程执行UI刷新
                .sink { [weak self] _ in
                    self?.tableView.reloadData()
                }
                .store(in: &cancellables)
            
            // 初始加载数据
            viewModel.getProfiles()
        }
    
        // 省略UITableView数据源与代理方法
    }
    
  2. 确保ViewModel的getProfiles方法正确更新profiles数组
    如果getProfiles包含异步操作(比如网络请求),必须在主线程更新profiles数组,因为UI操作只能在主线程执行。示例:

    class ProfilesViewModel: ObservableObject {
        @Published var profiles: [Profile] = []
    
        func getProfiles() {
            // 模拟异步数据请求
            DispatchQueue.global().async {
                // 假设此处获取到新的profiles数据
                let newProfiles = [Profile(name: "示例1"), Profile(name: "示例2")]
                DispatchQueue.main.async {
                    self.profiles = newProfiles
                }
            }
        }
    }
    
  3. 保证UIHostingController传入的是同一个ViewModel实例
    创建UIHostingController展示ProfilesMenu时,必须传入和UIKit视图控制器完全相同的ViewModel对象,这样SwiftUI中调用viewModel.getProfiles才会触发同一个实例的profiles更新,进而被UIKit视图控制器的订阅监听到。示例:

    // 在UIKit视图控制器中创建并展示SwiftUI视图
    let profilesMenu = ProfilesMenu(viewModel: viewModel)
    let hostingController = UIHostingController(rootView: profilesMenu)
    // 展示hostingController的代码,如present或添加为子控制器
    present(hostingController, animated: true)
    

完成以上配置后,当你在ProfilesMenu中调用viewModel.getProfiles更新profiles数组时,UIKit视图控制器的订阅会收到通知,自动触发UITableView的刷新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 00:15:34