You need to enable JavaScript to run this app. 在UIViewController中声明@Published属性传递给SwiftUI的变化监听实现
优惠活动
大模型
产品
解决方案
定价
更多

在UIViewController中声明@Published属性传递给SwiftUI的变化监听实现

直接结论

完全可以实现你描述的状态跨侧同步逻辑,但你原代码无法编译的核心问题是错把SwiftUI专属的@State属性包装器用在了UIViewController类中。
@State是专门为值类型的SwiftUI视图设计的状态存储,它的初始化逻辑强依赖SwiftUI的视图上下文,根本不支持在引用类型的UIKit控制器中正常工作——用在UIViewController里首先就会触发编译报错,就算强行绕过编译,既没法触发Combine订阅,也没法生成合法的双向绑定值传给SwiftUI。

正确实现逻辑

你要的“控制器持有状态、把双向绑定传给SwiftUI视图、SwiftUI侧修改值时控制器可收到通知”的链路,完全可以通过Combine的@Published实现,核心是替换掉错用的@State:

  1. 在UIViewController中把待同步的状态标记为@Published属性
  2. 手动将@Published的属性桥接为SwiftUI可识别的Binding实例,传给UIHostingController承载的SwiftUI视图
  3. 在VC的初始化流程中通过Combine订阅@Published的变化流,接收SwiftUI侧的修改通知

对应的可运行代码示例:

class MyVC: UIViewController {
    // 替换掉原代码里错用的@State
    @Published var myBoolState: Bool = false
    private var subscribers = Set<AnyCancellable>()

    override func viewDidLoad() {
        super.viewDidLoad()
        // 订阅状态变更,这里会收到包括初始值在内的所有状态更新
        $myBoolState
            .sink { newState in
                // 在这里处理SwiftUI侧传回的状态变化
                print("状态更新为:\(newState)")
            }
            .store(in: &subscribers)
    }

    func createTheView() {
        // 把@Published属性桥接为SwiftUI可用的Binding,不能直接把$myBoolState传给SwiftUI
        let stateBinding = Binding(
            get: { self.myBoolState },
            set: { self.myBoolState = $0 }
        )
        let hostingVC = UIHostingController(
            rootView: MySwiftUIView(myBoolState: stateBinding)
        )
        navigationController?.pushViewController(hostingVC, animated: true)
    }
}

struct MySwiftUIView: View {
    // 这部分原代码写法完全正确,不需要修改
    @Binding var myBoolState: Bool

    var body: some View {
        Button(action: {
            myBoolState = true
        }) {
            Text("Push Me")
        }
    }
}
工程优化提示
  • 如果不想每次创建HostingController都手写Binding的get/set闭包,可以单独抽一个遵循ObservableObject的状态类,把所有@Published的待同步状态都存在这个类里,VC和SwiftUI视图都引用同一个状态实例,既简化绑定代码,也方便状态的统一管理
  • @Published的发布流会在订阅建立时自动发送一次当前属性值,如果不需要初始值触发回调,可以在sink调用前链式加上.dropFirst()过滤掉初始事件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.04 13:27:02