Wil*_* Hu 1 ios swift swiftui combine
我有一个视图(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())
Run Code Online (Sandbox Code Playgroud)
如果MainViewModel发生currentFoo变化,则应更新 UI。
当单击foo1或 时foo2,selectedFooinFooGroupViewModel已更新,则 inMainViewModel应该得到更改(如@ObservedObject var fooGroupViewModel: FooGroupViewModel)
我的问题是如何让知道incurrentFoo的变化?我认为这一行可以观察 的变化,如果有任何更新,则触发更改并更新 UI。selectedFoofooGroupViewModelselectedFoocurrentFoo
currentFoo = self.fooGroupViewModel.selectedFoo
Run Code Online (Sandbox Code Playgroud)
但实际上是行不通的。
有什么帮助吗?谢谢!
我还有另一个问题,它是上面代码中的注释(如果将我的代码粘贴到 Playground 中,则为第 56 行)
ForEach(viewModel.foos) { foo in
Text(foo.name)
}
Run Code Online (Sandbox Code Playgroud)
这段代码使操场错误:
// 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.
Run Code Online (Sandbox Code Playgroud)
控制台中没有任何其他信息。不知道为什么。谢谢你的帮助。
仅仅这样做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)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2986 次 |
| 最近记录: |