我做了一个反向bool绑定的测试代码如下,几乎包括了我能想到的绑定方式
struct TestView: View {
@State private var isOn: Bool = false
@State private var parameter: Parameter = .init()
@StateObject private var vm = ViewModel()
var body: some View {
VStack {
Toggle("isOff = \(isOn.description)", isOn: !$isOn)
Toggle("isOff = \(parameter.isOn.description)", isOn: !$parameter.isOn)
Toggle("isOff = \(vm.isOn.description)", isOn: !$vm.isOn)
Toggle("isOff = \(vm.parameter.isOn.description)", isOn: !$vm.parameter.isOn)
InnerView { isOn in
Toggle("isOff = \(isOn.wrappedValue.description)", isOn: !isOn)
} t2: { parameter in
Toggle("isOff = \(parameter.wrappedValue.isOn.description)", isOn: !parameter.isOn)
}
}
.padding()
}
@MainActor
class ViewModel: ObservableObject {
@Published var isOn: Bool = false
@Published var parameter: Parameter = .init()
}
struct Parameter {
var isOn: Bool = false
}
struct InnerView<T>: View where T: View {
@State private var isOn: Bool = false
@State private var parameter: Parameter = .init()
let t1: (Binding<Bool>) -> T
let t2: (Binding<Parameter>) -> T
var body: some View {
VStack {
t1($isOn)
t2($parameter)
}
}
}
}
Q1:这里定义前缀运算符!有两种方式:全局绑定和扩展绑定。哪个有效?如果放在一起,它们不会冲突,如果评论一个和另一个工作正常。
prefix operator !
prefix func !(value: Binding<Bool>) -> Binding<Bool> {
Binding<Bool>(
get: { !value.wrappedValue },
set: { value.wrappedValue = !$0 }
)
}
extension Binding where Value == Bool {
static prefix func !(value: Binding<Bool>) -> Binding<Bool> {
Binding<Bool>(
get: { !value.wrappedValue },
set: { value.wrappedValue = !$0 }
)
}
}
如果我评论全局的,然后像下面这样更改扩展名,奇怪的事情发生了,编译成功并运行运行崩溃。
//prefix operator !
//
//prefix func !(value: Binding<Bool>) -> Binding<Bool> {
// Binding<Bool>(
// get: { !value.wrappedValue },
// set: { value.wrappedValue = !$0 }
// )
//}
extension Binding where Value == Bool {
static prefix func !(value: Binding<Bool>) -> Binding<Bool> {
!value
}
}
Q2:如果我把前缀运算符!定义到 Swift 包框架中,一些测试将编译失败,因为 '无法将类型 'Binding' 的值转换为预期的参数类型 'Bool'。无法将“Bool”类型的值转换为预期的参数类型“Binding”。是 Swift Package 的定义方式不对还是有什么问题?