我有一个 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")
}
}
Run Code Online (Sandbox Code Playgroud)
但我想为所有符合 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
}
}
Run Code Online (Sandbox Code Playgroud)
我可以让 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)
}
}
Run Code Online (Sandbox Code Playgroud)
这意味着我可以重用我的 @Published 变量,但这不会扩展,因为不允许多重继承。
这严重限制了我的代码可重用性。必须有一种方法以更具可扩展性的方式实现这一目标。有任何想法吗?要求是让 ParentView 接受 Generic ViewModel 参数。
小智 0
你能不能不使用
@EnvironmentObject var myViewModel: MyViewModel
Run Code Online (Sandbox Code Playgroud)
在您的视图中您需要访问它。然后将其用作
myViewModel.soundOn
Run Code Online (Sandbox Code Playgroud)
您不需要将其作为绑定在视图之间传递,因为您可以在声明 @EnvironmentObject 的任何视图中访问 soundOn。
| 归档时间: |
|
| 查看次数: |
4055 次 |
| 最近记录: |