SwiftUI:单例 class 未更新视图

SwiftUI: Singleton class not updating view

SwiftUI 新手...我有以下简化代码。预期的功能是能够在 View1()View2() 之间导航,使用单例 class 来跟踪此导航。

我怀疑我可能需要将 @Published 添加到我的 show_view_2 变量中,但我想将其保留在 App Storage 中。另外,我知道这不是在视图之间切换的最佳方式,但我之所以使用这种方法只是因为它是一个最少复制的示例。

为什么下面的代码不起作用,我怎样才能让它起作用?

class Player {
    static var player = Player()
    @AppStorage("show_view_2") var show_view_2: Bool = false
}

struct ContentView: View {  
    var body: some View {
        if(Player.player.show_view_2) {
            View2()
        } else {
            Text("Go to View2")
                .onTapGesture {
                    Player.player.show_view_2 = true
                }
        }
    }
}

struct View2: View {
    var body: some View {
        Text("Back to View1")
            .onTapGesture {
                Player.player.show_view_2 = false
            }
    }
}

要让 SwiftUI 知道要更新,Player 应该是 ObservableObject。此外,需要在 View:

上使用 属性 包装器(@StateObject@ObservedObject)访问它
class Player : ObservableObject {
    static var player = Player()
    @AppStorage("show_view_2") var show_view_2: Bool = false
}

struct ContentView: View {
    @StateObject private var player = Player.player
    
    var body: some View {
        if player.show_view_2 {
            View2()
        } else {
            Text("Go to View2")
                .onTapGesture {
                    player.show_view_2 = true
                }
        }
    }
}

struct View2: View {
    @StateObject private var player = Player.player
    
    var body: some View {
        Text("Back to View1")
            .onTapGesture {
                player.show_view_2 = false
            }
    }
}

一般来说,我建议不要使用单例,而是在视图之间显式传递对象的实例——随着时间的推移,这将更易于测试和灵活:

class Player : ObservableObject {
    @AppStorage("show_view_2") var show_view_2: Bool = false
}

struct ContentView: View {
    @StateObject private var player = Player()
    
    var body: some View {
        if player.show_view_2 {
            View2(player: player)
        } else {
            Text("Go to View2")
                .onTapGesture {
                    player.show_view_2 = true
                }
        }
    }
}

struct View2: View {
    @ObservedObject var player : Player
    
    var body: some View {
        Text("Back to View1")
            .onTapGesture {
                player.show_view_2 = false
            }
    }
}