SwiftUI Combine:当 属性 存储在不同的视图模型中时,TabView 不会在选择时更新

SwiftUI Combine: TabView is not updating on selection when property stored in different viewmodel

我正在使用页面样式开发Tabview,我想在按钮操作上滚动tabview。在 NavigationMenu.

内添加了按钮

NavigationMenu查看NavigationModel(ViewModel)分开一个parent.

选择处理在 NavigationModel 内完成。

在标签页上滑动我可以看到 NavigationMenu 中的变化,这很好。

但是如果我点击按钮,tabview 页面不会滑动。即使我在方法 onReceive.

上收到更改事件

代码:

import SwiftUI
import Combine

final class NavigationModel: ObservableObject {
    @Published var selectedItem = ""
    @Published var items: [String] = [
        "Button 1", "Button 2", "Button 3"
    ]
}

struct NavigationMenu: View {

    @ObservedObject var viewModel: NavigationModel

    var body: some View {
        HStack {
            ForEach(0..<3, id: \.self) { index in
                let title = viewModel.items[index]
                Button {
                    viewModel.selectedItem = title
                } label: {
                    Text(title)
                        .font(.system(.body))
                        .padding()
                        .foregroundColor(
                            viewModel.selectedItem == title ? .white : .black
                        )
                        .background(viewModel.selectedItem == title ? .black : .yellow)
                }
            }
        }
    }
}

final class TabViewModel: ObservableObject {
    var navModel = NavigationModel()
}

struct TabviewWithMenuView: View {

    @ObservedObject var viewModel = TabViewModel()

    var body: some View {
        parentView
    }

    private var parentView: some View {
        VStack(spacing: 0) {
            Spacer()
            NavigationMenu(viewModel: viewModel.navModel)
            pageView
        }
        .onReceive(viewModel.navModel.$selectedItem) { output in
            print("Button tapped:", output)
        }
    }

    private var pageView: some View {
        TabView(selection: $viewModel.navModel.selectedItem) {
            ForEach(0..<3, id: \.self) { index in
                let tag = viewModel.navModel.items[index]
                item(tag: tag)
                    .tag(tag)
            }
        }
        .tabViewStyle(.page(indexDisplayMode: .never))
        .transition(.slide)
    }

    private func item(tag: String) -> some View {
        VStack {
            Text("PAGE: " + tag)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.red)
    }

}

图片:

没有观察到ObservableObject内部的ObservableObject,我们需要显式观察被改变的实例。

在这种情况下,一个可能的解决方案是分离 PageView 并向其注入导航视图模型,以便对其进行观察。

测试 Xcode 13.3 / iOS 15.4

这是主要部分:


    NavigationMenu(viewModel: viewModel.navModel)
    PageView(navModel: viewModel.navModel)

    ...

    struct PageView: View {
        @ObservedObject var navModel: NavigationModel

        var body: some View {
            pageView
        }
        // ....
    }

Test module in project is here