我有一个视图(MainView
),里面有另一个视图(FooGroupView
)。每次我单击FooGroupView
中的项目,然后将值更改传递到MainView
。
像下面这样:
白色视图为MainView
,红色视图为FooGroupView
。如果单击foo1
,则文本应为Current:foo1
,然后单击foo2
,然后单击Current:foo2
。
我的代码在这里:
测试场
import SwiftUI
import PlaygroundSupport
struct FooRowView: View {
var foo: Foo
var body: some View {
VStack {
Color(.red)
Text(foo.name)
}
}
}
class Foo: Identifiable, ObservableObject {
var name: String
var id: String
init(name: String, id: String) {
self.name = name
self.id = id
}
}
final class FooGroupViewModel: ObservableObject {
var foos: [Foo] {
didSet {
self.selectedFoo = foos.first
}
}
@Published var selectedFoo: Foo? {
didSet {
print("You selected: \(selectedFoo?.name)")
}
}
init(foos: [Foo] = []) {
self.foos = foos
self.selectedFoo = foos.first
}
}
struct FooGroupView: View {
var viewModel: FooGroupViewModel
var body: some View {
ScrollView(.horizontal) {
HStack(alignment: .center, spacing: 32, content: {
// Error: error: Execution was interrupted, reason: signal SIGABRT.
//The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
/*ForEach(viewModel.foos) { foo in
Text(foo.name)
}*/
Text(viewModel.foos[0].name).onTapGesture {
viewModel.selectedFoo = viewModel.foos[0]
}
Text(viewModel.foos[1].name).onTapGesture {
viewModel.selectedFoo = viewModel.foos[1]
}
})
}
}
}
final class MainViewModel: ObservableObject {
@ObservedObject var fooGroupViewModel: FooGroupViewModel
@Published var currentFoo: Foo?
init() {
fooGroupViewModel = FooGroupViewModel(foos: [Foo(name: "foo1", id: "1"), Foo(name: "foo2", id: "2")])
currentFoo = self.fooGroupViewModel.selectedFoo
}
}
struct MainView: View {
@ObservedObject var viewModel = MainViewModel()
var body: some View {
VStack {
FooGroupView(viewModel: viewModel.fooGroupViewModel)
.background(Color.red)
Spacer()
Text("Current:\(viewModel.currentFoo!.name)")
}.frame(width: 200, height: 200)
}
}
PlaygroundPage.current.liveView = UIHostingController(rootView: MainView())
在MainViewModel
中,如果currentFoo
有所更改,则应该更新UI。
单击foo1
或foo2
时,selectedFoo
中的FooGroupViewModel
已更新,则MainViewModel
中的@ObservedObject var fooGroupViewModel: FooGroupViewModel
应该得到更改(如currentFoo
)
我的问题是如何让selectedFoo
知道fooGroupViewModel
中selectedFoo
的变化?我以为这行代码可以观察currentFoo
的更改,如果有更新,则触发currentFoo = self.fooGroupViewModel.selectedFoo
更改并更新UI。
ForEach(viewModel.foos) { foo in
Text(foo.name)
}
但是实际上不起作用。
有帮助吗?谢谢!
我还有另一个问题,就是上面代码中的注释(如果将我的代码粘贴到Playground中,则为第56行)
// Error: error: Execution was interrupted, reason: signal SIGABRT.
//The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
此代码使游乐场出错:
const path = require("path");
module.exports = {
mode: "none",
entry: ["core-js/stable", "./src/js/index.js"],
output: {
path: path.resolve(__dirname + "/dist"),
filename: "bundle.js",
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: [[
"@babel/preset-env",{
"useBuiltIns": "usage",
"corejs" : {
version : "3",
proposals : true
},
"targets" : {
"browsers": ["last 3 versions", "ie >= 11"],
"node": "current"
}
}
]],
plugins: ["@babel/transform-runtime"]
}
}
}
]
},
// devtool: "eval-source-map"
}
在控制台中没有任何其他信息。不知道为什么。感谢您的帮助。
答案 0 :(得分:1)
仅仅做currentFoo = self.fooGroupViewModel.selectedFoo
绝对行不通-只是将currentFoo
当时的情况分配给selectedFoo
。
在设置后,您需要订阅fooGroupViewModel.selectedFoo
中的更改,这可以通过Published
发布者完成,因为它是@Published
属性,因此可用。
此外,请记住,@ObservedObject
仅在视图内有意义,因此我将其删除。
import Combine
// ...
final class MainViewModel: ObservableObject {
var fooGroupViewModel: FooGroupViewModel
@Published var currentFoo: Foo?
private var cancellables: Set<AnyCancellable> = []
init() {
fooGroupViewModel = FooGroupViewModel(foos:
[Foo(name: "foo1", id: "1"), Foo(name: "foo2", id: "2")])
fooGroupViewModel.$selectedFoo
.assign(to: \.currentFoo, on: self)
.store(in: &cancellables)
}
}