SwiftUI中如何创建与同一变量反向绑定的Toggle?
SwiftUI实现绑定同一变量的反向Toggle按钮
我想创建一个包含两个Toggle按钮的视图,它们绑定同一个布尔变量,但其中一个Toggle的状态是该变量的反向——只有当原变量为false时,这个Toggle才处于选中状态。
之前的错误尝试
尝试1:直接用感叹号反转绑定
最初我尝试直接在绑定变量前加感叹号反转:
Toggle(isOn: $myStruct.myBooleanVar) { Text("Yes").frame(width: 80) }.toggleStyle(.button) Toggle(isOn: $myStruct.!myBooleanVar) { Text("no").frame(width: 80) }.toggleStyle(.button)
结果报错:
'.!' is not a binary operator
尝试2:寻找反转修饰符
之后我想找有没有能反转Toggle状态的修饰符,尝试这样写:
Toggle(isOn: $myStruct.myBooleanVar) { Text("Yes").frame(width: 80) }.toggleStyle(.button) Toggle(isOn: $myStruct.myBooleanVar) { Text("no").frame(width: 80) }.toggleStyle(.button) .inverted(true)
但SwiftUI里并没有这类修饰符。
尝试3:使用临时变量/自定义绑定
接着我尝试用临时变量、状态变量或者自定义绑定来实现,但都遇到同一个报错:
Cannot use instance member 'settings' within property initializer; property initializers run before 'self' is available
正确实现方式
要实现反向绑定,核心是手动创建Binding<Bool>,通过get和set方法反转值,同时避开属性初始化器中无法引用self的问题,以下是几种可行方案:
方案1:在body里创建自定义绑定
直接在视图的body中定义反向绑定,避开初始化阶段的self问题:
struct ContentView: View { @State private var myStruct = MyStruct(myBooleanVar: false) var body: some View { // 定义反向绑定 let reversedBinding = Binding<Bool>( get: { !self.myStruct.myBooleanVar }, set: { self.myStruct.myBooleanVar = !$0 } ) HStack { Toggle(isOn: $myStruct.myBooleanVar) { Text("Yes").frame(width: 80) }.toggleStyle(.button) Toggle(isOn: reversedBinding) { Text("No").frame(width: 80) }.toggleStyle(.button) } } } struct MyStruct { var myBooleanVar: Bool }
方案2:用计算属性封装反向绑定
如果需要多次使用反向绑定,可以把它封装成视图的计算属性:
struct ContentView: View { @State private var myStruct = MyStruct(myBooleanVar: false) // 封装反向绑定为计算属性 private var reversedMyBoolean: Binding<Bool> { Binding( get: { !myStruct.myBooleanVar }, set: { myStruct.myBooleanVar = !$0 } ) } var body: some View { HStack { Toggle(isOn: $myStruct.myBooleanVar) { Text("Yes").frame(width: 80) }.toggleStyle(.button) Toggle(isOn: reversedMyBoolean) { Text("No").frame(width: 80) }.toggleStyle(.button) } } }
方案3:扩展Binding实现通用反转
给Binding<Bool>写个扩展,让所有布尔绑定都能直接调用反转方法:
// 扩展Binding,添加反转功能 extension Binding where Value == Bool { var reversed: Binding<Bool> { Binding( get: { !self.wrappedValue }, set: { self.wrappedValue = !$0 } ) } } // 使用示例 struct ContentView: View { @State private var myStruct = MyStruct(myBooleanVar: false) var body: some View { HStack { Toggle(isOn: $myStruct.myBooleanVar) { Text("Yes").frame(width: 80) }.toggleStyle(.button) // 直接调用.reversed获取反向绑定 Toggle(isOn: $myStruct.myBooleanVar.reversed) { Text("No").frame(width: 80) }.toggleStyle(.button) } } }
内容的提问来源于stack exchange,提问作者SwiftlySlow
相关产品推荐
相关产品推荐

