SwiftUI:如何为环境对象ViewModel的属性创建Binding?
将Observable ViewModel的属性绑定传递给子View的实现方法
你需要把环境中ViewModel的showDetails属性以Binding形式传递给DetailsButton,有两种简洁的实现方式,适配iOS 17/macOS 14的新Observation框架:
方式一:用@Bindable包装环境ViewModel(推荐)
通过@Bindable修饰环境中的Observable对象,就能像使用@State一样用$语法直接生成Binding,写法最简洁:
完整代码
@Observable class ViewModel { var showDetails: Bool // 添加默认初始化方法,方便实例化 init(showDetails: Bool = false) { self.showDetails = showDetails } } struct TestApp: App { @State var vm = ViewModel() var body: some Scene { WindowGroup { ContentView() .environment(vm) } } } struct ContentView: View { // 用@Bindable和@Environment组合,直接生成可绑定的ViewModel实例 @Bindable @Environment(ViewModel.self) private var vm var body: some View { VStack { // 直接传递$vm.showDetails,和原示例的用法一致 DetailsButton(showDetails: $vm.showDetails) if vm.showDetails { Text("This is my message!") } } } } struct DetailsButton: View { @Binding var showDetails: Bool var body: some View { Button("\(showDetails ? "Hide" : "Show") Details") { showDetails.toggle() } } }
方式二:手动构造Binding
如果需要自定义属性的读取/赋值逻辑,可以手动通过Binding(get:set:)构造器生成绑定:
完整代码
@Observable class ViewModel { var showDetails: Bool init(showDetails: Bool = false) { self.showDetails = showDetails } } struct TestApp: App { @State var vm = ViewModel() var body: some Scene { WindowGroup { ContentView() .environment(vm) } } } struct ContentView: View { @Environment(ViewModel.self) private var vm var body: some View { VStack { DetailsButton( showDetails: Binding( get: { vm.showDetails }, set: { vm.showDetails = $0 } ) ) if vm.showDetails { Text("This is my message!") } } } } struct DetailsButton: View { @Binding var showDetails: Bool var body: some View { Button("\(showDetails ? "Hide" : "Show") Details") { showDetails.toggle() } } }
两种方式都能实现和原示例完全一致的功能,推荐使用方式一,语法更符合SwiftUI的设计习惯。
内容的提问来源于stack exchange,提问作者Anton
相关产品推荐
相关产品推荐

