【发布时间】:2020-07-10 12:30:59
【问题描述】:
我有一个 ParentView,我想将 @Published 变量传递给一个子视图,在那里它将用作 @Bindable。
这在像这样使用 MyViewModel 时有效:
class MyViewModel: ObservableObject {
@Published var soundOn = true
}
struct ParentView: View {
@ObservedObject var myViewModel: MyViewModel
var body: some View {
Subview(soundOn: $myViewModel.soundOn)
}
}
struct Subview: View {
@Binding var soundOn: Bool
var body: some View {
Image(soundOn ? "soundOn" : "soundOff")
}
}
但我想为所有符合 HasSoundOnOff 协议的 ViewModel 重用 Subview。 使用 HasSoundOnOff 协议时,我无法在协议中定义 @Published,这意味着 ParentView 只能看到一个普通的非@Published 变量,并且不能使用 $viewModel.soundOn。
protocol HasSoundOnOff {
var soundOn: Bool { get set }
}
class MyViewModel: HasSoundOnOff {
@Published var soundOn = true
}
struct ParentView<ViewModel: ObservableObject & HasSoundOnOff>: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
Subview(soundOn: $viewModel.soundOn) //<----- error: "Expression type 'Binding<_>' is ambiguous without more context" because protocols can't have @Published and therefor soundOn is treated like a non-@Published variable
}
}
我可以让 MyViewModel 从定义 @Published 变量的类继承,所以下面的代码可以工作:
class InheritFromPublishedVarClass: ObservableObject {
@Published var soundOn = true
}
class MyViewModel: ObservableObject & InheritFromPublishedVarClass {}
struct ParentView<ViewModel: ObservableObject & InheritFromPublishedVarClass>: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
Subview(soundOn: $viewModel.soundOn)
}
}
这意味着我可以重用我的 @Published 变量,但这不会扩展,因为不允许多重继承。
这严重限制了我的代码可重用性。必须有一种方法以更具可扩展性的方式实现这一目标。 有任何想法吗? 要求是让 ParentView 接受 Generic ViewModel 参数。
【问题讨论】:
-
C++ 遗留(多重继承)?没有限制,只需重新考虑您的设计,例如,将
InheritFromPublishedVarClass用作HasSoundOnOffBase非常基类。协议不能通过语言设计来存储属性(因此不排除 @Published,它只是存储属性的属性包装器)。 -
谢谢,你能不能给我看一个实际的例子?