SwiftUI 双向绑定到枚举案例中 ObservableObject 中的值
Posted
技术标签:
【中文标题】SwiftUI 双向绑定到枚举案例中 ObservableObject 中的值【英文标题】:SwiftUI two-way binding to value inside ObservableObject inside enum case 【发布时间】:2020-05-26 18:57:04 【问题描述】:我正在尝试观察 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
的值,但由于我想要ObservableObject
包含enum
中的属性,例如CustomEnum
不知道该怎么做,或者如果它是甚至可能。我选择了一个枚举,因为会有多个具有不同ObservableObject
值的枚举选项,并且Parent
将根据CustomEnum
选项生成不同的子视图。如果它具有任何相关性,则Parent
将从Array
的CustomEnum
值中接收myCustomEnum
值。这甚至可能吗?如果没有,我有什么选择?谢谢!
【问题讨论】:
问题是您只能获得声明为@ObservedObject
的变量的$obj.prop
语法——而不是ObservableObject
。
【参考方案1】:
好吧,永远不要说永远...我已经为这种情况找到了有趣的解决方案,它甚至允许删除 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
private func processCases() -> some View
switch myCustomEnum
case .option1(let type1Value):
// main part !!
return 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)
【讨论】:
这确实有效,但如果您有第二个类型,如.option2(let type2Value)
,其值为 Child2
,则返回类型仍需要包含在 AnyView
中,但无论如何,这都按预期工作.谢谢百万!【参考方案2】:
这可能适用于您的情况:
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()
)
【讨论】:
以上是关于SwiftUI 双向绑定到枚举案例中 ObservableObject 中的值的主要内容,如果未能解决你的问题,请参考以下文章