SwiftUI 双向绑定到枚举案例中 ObservableObject 中的值
SwiftUI two-way binding to value inside ObservableObject inside enum case
我正在尝试观察 ObservableObject
中包含的 bool
值的变化,这是 enum
情况下的值。这是我试图实现的示例,但使用当前方法我收到错误 Use of unresolved identifier '$type1Value'
.
import SwiftUI
import Combine
class ObservableType1: ObservableObject {
@Published var isChecked: Bool = false
}
enum CustomEnum {
case option1(ObservableType1)
}
struct Parent: View {
var myCustomEnum: CustomEnum
var body: AnyView {
switch myCustomEnum {
case .option1(let type1Value):
AnyView(Child(isChecked: $type1Value.isChecked)) // <- error here
}
}
}
struct Child: View {
@Binding var isChecked: Bool
var body: AnyView {
AnyView(
Image(systemName: isChecked ? "checkmark.square" : "square")
.onTapGesture {
self.isChecked = !self.isChecked
})
}
}
我正在尝试从界面更新 isChecked
的值,但因为我想要包含 enum
中的 属性 的 ObservableObject
,例如 CustomEnum
不知道该怎么做,或者是否有可能。我选择了一个枚举,因为会有多个具有不同 ObservableObject
值的枚举选项,并且 Parent
将根据 CustomEnum
选项生成不同的子视图。如果它有任何相关性,Parent
将从 Array
的 CustomEnum
值中接收 myCustomEnum
值。这可能吗?如果没有,我有什么选择?谢谢!
这可能适用于您的情况:
import SwiftUI
class ObservableType1: ObservableObject {
@Published var isChecked: Bool = false
}
enum CustomEnum {
case option1(ObservableType1)
}
struct Parent: View {
var myCustomEnum: CustomEnum
var body: AnyView {
switch (myCustomEnum) {
case .option1:
return AnyView(Child())
default: return AnyView(Child())
}
}
}
struct Child: View {
@ObservedObject var type1 = ObservableType1()
var body: AnyView {
AnyView(
Image(systemName: self.type1.isChecked ? "checkmark.square" : "square")
.onTapGesture {
self.type1.isChecked.toggle()
})
}
}
好吧,永远不要说永远......我已经找到了针对这种情况的有趣解决方案,它甚至允许删除 AnyView。使用 Xcode 11.4 / iOS 13.4
测试
提供完整的可测试模块,以防万一。
// just for test
struct Parent_Previews: PreviewProvider {
static var previews: some View {
Parent(myCustomEnum: .option1(ObservableType1()))
}
}
// no changes
class ObservableType1: ObservableObject {
@Published var isChecked: Bool = false
}
// no changes
enum CustomEnum {
case option1(ObservableType1)
}
struct Parent: View {
var myCustomEnum: CustomEnum
var body: some View {
self.processCases() // function to make switch work
}
@ViewBuilder
private func processCases() -> some View {
switch myCustomEnum {
case .option1(let type1Value):
ObservedHolder(value: type1Value) { object in
Child(isChecked: object.isChecked)
}
}
}
// just remove AnyView
struct Child: View {
@Binding var isChecked: Bool
var body: some View {
Image(systemName: isChecked ? "checkmark.square" : "square")
.onTapGesture {
self.isChecked = !self.isChecked
}
}
}
这是一个组织者
struct ObservedHolder<T: ObservableObject, Content: View>: View {
@ObservedObject var value: T
var content: (ObservedObject<T>.Wrapper) -> Content
var body: some View {
content(_value.projectedValue)
}
}
我正在尝试观察 ObservableObject
中包含的 bool
值的变化,这是 enum
情况下的值。这是我试图实现的示例,但使用当前方法我收到错误 Use of unresolved identifier '$type1Value'
.
import SwiftUI
import Combine
class ObservableType1: ObservableObject {
@Published var isChecked: Bool = false
}
enum CustomEnum {
case option1(ObservableType1)
}
struct Parent: View {
var myCustomEnum: CustomEnum
var body: AnyView {
switch myCustomEnum {
case .option1(let type1Value):
AnyView(Child(isChecked: $type1Value.isChecked)) // <- error here
}
}
}
struct Child: View {
@Binding var isChecked: Bool
var body: AnyView {
AnyView(
Image(systemName: isChecked ? "checkmark.square" : "square")
.onTapGesture {
self.isChecked = !self.isChecked
})
}
}
我正在尝试从界面更新 isChecked
的值,但因为我想要包含 enum
中的 属性 的 ObservableObject
,例如 CustomEnum
不知道该怎么做,或者是否有可能。我选择了一个枚举,因为会有多个具有不同 ObservableObject
值的枚举选项,并且 Parent
将根据 CustomEnum
选项生成不同的子视图。如果它有任何相关性,Parent
将从 Array
的 CustomEnum
值中接收 myCustomEnum
值。这可能吗?如果没有,我有什么选择?谢谢!
这可能适用于您的情况:
import SwiftUI
class ObservableType1: ObservableObject {
@Published var isChecked: Bool = false
}
enum CustomEnum {
case option1(ObservableType1)
}
struct Parent: View {
var myCustomEnum: CustomEnum
var body: AnyView {
switch (myCustomEnum) {
case .option1:
return AnyView(Child())
default: return AnyView(Child())
}
}
}
struct Child: View {
@ObservedObject var type1 = ObservableType1()
var body: AnyView {
AnyView(
Image(systemName: self.type1.isChecked ? "checkmark.square" : "square")
.onTapGesture {
self.type1.isChecked.toggle()
})
}
}
好吧,永远不要说永远......我已经找到了针对这种情况的有趣解决方案,它甚至允许删除 AnyView。使用 Xcode 11.4 / iOS 13.4
测试提供完整的可测试模块,以防万一。
// just for test
struct Parent_Previews: PreviewProvider {
static var previews: some View {
Parent(myCustomEnum: .option1(ObservableType1()))
}
}
// no changes
class ObservableType1: ObservableObject {
@Published var isChecked: Bool = false
}
// no changes
enum CustomEnum {
case option1(ObservableType1)
}
struct Parent: View {
var myCustomEnum: CustomEnum
var body: some View {
self.processCases() // function to make switch work
}
@ViewBuilder
private func processCases() -> some View {
switch myCustomEnum {
case .option1(let type1Value):
ObservedHolder(value: type1Value) { object in
Child(isChecked: object.isChecked)
}
}
}
// just remove AnyView
struct Child: View {
@Binding var isChecked: Bool
var body: some View {
Image(systemName: isChecked ? "checkmark.square" : "square")
.onTapGesture {
self.isChecked = !self.isChecked
}
}
}
这是一个组织者
struct ObservedHolder<T: ObservableObject, Content: View>: View {
@ObservedObject var value: T
var content: (ObservedObject<T>.Wrapper) -> Content
var body: some View {
content(_value.projectedValue)
}
}