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
}
// ....
}
我正在使用页面样式开发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
}
// ....
}