SwiftUI @StateObject 无法刷新视图

时间:2021-03-19 19:04:20

标签: xcode swiftui observedobject

我在 ContentView 页面上看不到 Text 对象的变化。但是,当我使用打印在 .onReceive 中运行相同的代码时,我可以看到更改。这里有什么问题?

我想从不同的地方管理游戏的状态,从不同的地方管理游戏的运行。是不是我逻辑错了?

枚举

enum GameSituation {
    case play
}

游戏配置

class GameConfig: ObservableObject {
    @Published var randomCellValue: Int = 0
    @Published var timer = Timer.publish(every: 2, on: .main, in: .common).autoconnect()
    
    func startGame() {
        determineRandomCell()
    }
    
    func determineRandomCell() {
        randomCellValue = Int.random(in: 0...11)
    }

    func playSound(soundfile: String, ofType: String) {
        
        if let path = Bundle.main.path(forResource: soundfile, ofType: ofType){
            do{
                audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path))
                audioPlayer.prepareToPlay()
                audioPlayer.play()
            } catch {
                print("Error")
            }
        }
    }
}

游戏情况

class GameSituations: ObservableObject {
    @Published var gameConfig = GameConfig()
    
    func gameSituation(gameSituation: GameSituation) {
        switch gameSituation {
        case .play:
            gameConfig.startGame()
        }
    }
}

内容视图

struct ContentView: View {
    @StateObject var gameSituation = GameSituations()
    var body: some View {
        Text("\(gameSituation.gameConfig.randomCellValue)")
            .padding()
            .onReceive(gameSituation.gameConfig.timer, perform: { _ in
                gameSituation.gameSituation(gameSituation: .play)
                print("random: \(gameSituation.gameConfig.randomCellValue)")
            })
    }
}

1 个答案:

答案 0 :(得分:0)

你有多个问题我都解决了,你的第一个也是大问题是,你正在初始化一个 ObservableObject 的实例,但使用另一个实例!第二个是您忘记在视图中使用 GameConfig 的 StateObject,正如您在代码中看到的,您确实使用了 GameSituations 的 StateObject 而不是 GameConfig,如果你问为什么,因为它是Publisher

我最好的建议:尝试只使用一个 ObservableObject!使用 2 个不同的 ObservableObject 绑定在一起有这样一个问题,你可以看到!尝试将所有代码组织到一个 ObservableObject


enum GameSituation {
    case play
}

class GameConfig: ObservableObject {
    
    static let shared: GameConfig = GameConfig()    // <<: Here

    @Published var randomCellValue: Int = 0
    @Published var timer = Timer.publish(every: 2, on: .main, in: .common).autoconnect()
    
    func startGame() {
        determineRandomCell()
    }
    
    func determineRandomCell() {
        randomCellValue = Int.random(in: 0...11)
    }

    func playSound(soundfile: String, ofType: String) {
        
        print(soundfile)


    }
}

class GameSituations: ObservableObject {
    
    static let shared: GameSituations = GameSituations()  // <<: Here

    let gameConfig = GameConfig.shared        // <<: Here
     
    func gameSituation(gameSituation: GameSituation) {
        switch gameSituation {
        case .play:
            gameConfig.startGame()
        }
    }
}

struct ContentView: View {
    
    @StateObject var gameSituation = GameSituations.shared     // <<: Here
    @StateObject var gameConfig = GameConfig.shared            // <<: Here
    
    var body: some View {
        
        Text(gameConfig.randomCellValue.description)          // <<: Here
            .onReceive(gameConfig.timer, perform: { _ in      // <<: Here

                       gameSituation.gameSituation(gameSituation: .play) 
                        print("random: \(gameSituation.gameConfig.randomCellValue)")
        
                    })

    }
}