【问题标题】:ObservableObject with ObservableObject property is not triggering SwiftUI Update具有 ObservableObject 属性的 ObservableObject 未触发 SwiftUI 更新
【发布时间】:2021-02-27 17:28:55
【问题描述】:
// NavigationState.swift
class NavigationState: ObservableObject {
    @Published var contentViewNavigation = ContentViewNavigationState()
    //@Published var selectedTab = 0
}

// App.swift
@main
struct SwiftUIDeepLinkApp: App {
    @StateObject private var navigationAppState = NavigationState()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(navigationAppState)
                .onAppear(perform: {
                    DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
                        print("Dispatch called")
                        navigationAppState.contentViewNavigation.selectedTab = 1
                        //navigationAppState.selectedTab = 1
                    }
                })
        }
    }
}

// ContentView.swift
class ContentViewNavigationState: ObservableObject {
    @Published var selectedTab = 0
}

struct ContentView: View {
    @EnvironmentObject var navigationState: NavigationState

    var body: some View {
        TabView(selection: $navigationState.contentViewNavigation.selectedTab) {
            HomeContainerFlow1()
                .tabItem { Text("Flow 1") }
                .tag(0)
        
            HomeContainerFlow2()
                .embededInNavigation()
                .tabItem { Text("Flow 2") }
                .tag(1)
        }.onReceive(navigationState.contentViewNavigation.$selectedTab, perform: { output in
            print("Value changed: \(output)")
        })
    }
}

如您所见,我正在定义一个全局状态(“NavigationState”)来处理应用程序的导航(即选项卡选择)。所以,我有一个 ObservableObject (NavigationState),它将具有每个屏幕导航状态的属性(即 ContentViewNavigationState - 另一个 ObservableObject)。

实际行为

在这个例子中,我在 DispatchQueue.asyncAfter 中修改 App.swift 文件中的状态,状态正在改变(因为 ContentView 的 onReceive 修饰符正在显示更新值),但没有触发 ContentView 中的任何更新。

预期行为

应根据状态更改所选选项卡。

  • 有趣的是,如果我还修改了另一个属性(即注释的 selectedTab),在这种情况下会触发更新,但不会在仅更新 contentViewNavigation 的属性时触发。

【问题讨论】:

    标签: swiftui observableobject swiftui-environment


    【解决方案1】:

    如果要在对象发生变化时更新,视图必须显式观察 ObservableObject。

    在您的情况下,您观察到可观察但不是内部可观察的父级。您方案中的 contentViewNavigation 不会自行更改,因为它只是对内部对象的引用。

    所以解决方案可能如下例所示

    struct ContentView: View {
        @EnvironmentObject var navigationState: NavigationState
    
        var body: some View {
           // separate view which observe inner ObservableObject
           MainView(contentNavigation: navigationState.contentViewNavigation)
        }
    }
    
    struct MainView: View {
        @ObservedObject var contentNavigation: ContentViewNavigationState
    
        var body: some View {
            TabView(selection: $contentNavigation.selectedTab) {
                HomeContainerFlow1()
                    .tabItem { Text("Flow 1") }
                    .tag(0)
            
                HomeContainerFlow2()
                    .embededInNavigation()
                    .tabItem { Text("Flow 2") }
                    .tag(1)
            }
        }
    }
    

    【讨论】:

    • 谢谢!但这意味着对于每个单独的视图,我必须像 ContentView 一样包装才能接收状态并传递所需的信息?
    猜你喜欢
    • 2020-10-25
    • 2020-12-05
    • 2020-05-24
    • 2021-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    • 1970-01-01
    相关资源
    最近更新 更多