swift - 使用嵌套模型更新 SwiftUI 中的 View

标签 swift data-binding swiftui

我正在尝试创建一个基本的井字棋游戏作为练习,但我无法根据存储游戏状态的模型(嵌套模型)更新我的 View ,我的代码就像以下:

TicTacToeModel 存储 SquareModel 数组,SquareModel 存储空、十字或无等状态。

因此,我想在每次用户按下空方 block 时更新我的​​模型,并使用该模型绘制“x”或“o”来更新我的 View

型号:

final class TicTacToeModel: ObservableObject{

    @Published var board = [SquareModel]()
    @Published var activePlayer = Player.x

    init(rowSize: Int) {
        self.rowSize = rowSize
        for _ in (0 ..< self.rowSize * self.rowSize){
            board.append(SquareModel(status: .empty))
        }
    }
}
class SquareModel: ObservableObject{
     @Published var status: Player = .empty

    init(status: Player) {
        self.status = status
    }
}

查看:

struct ContentView: View {

    @State var boardModel = TicTacToeModel(rowSize: Definitions().lines)

    func getIndex(row:Int, col:Int)-> Int{
        return row * Definitions().lines + col
    }

    func squareAction(index:Int){
        self.boardModel.makeMove(index: index, player: self.boardModel.activePlayer)
    }
    var body: some View {

         VStack {
            Spacer()
            TitleView()
            ZStack{
                BoardView()
                VStack{
                    ForEach(0..<Definitions().lines) { row in
                        HStack {
                            ForEach(0..<Definitions().lines) { col in
                                ZStack{
                                    SquareView (source: self.$boardModel.board[self.getIndex(row: row, col: col)]){
                                        let index = self.getIndex(row: row, col: col)
                                        self.squareAction(index: index)
                                    }
                                }

                            }
                        }
                    }
                }.aspectRatio(1, contentMode: .fit)
                .padding(20)
            }
            CurrentPlayerView(currentPlayer: self.boardModel.activePlayer)
            Spacer()
            Button(action: {
                self.boardModel.resetGame()
            }) {
                Text("Restart game!")
                    .font(.system(size: 30))
                    .fontWeight(.heavy)
                    .padding(.horizontal)
            }
            Spacer()
        }.padding(.horizontal)

    }
}
struct SquareView: View {
    @Binding var source: SquareModel
    var action: () -> Void
    var body: some View {
        xoImageView(player: source.status)
            .gesture(TapGesture().onEnded({ () in
            self.action()
        }))
    }
}

注意:模型工作正常并正确存储所有属性

最佳答案

ObservableObject/ObservedObject 被调整为 MVVM 中的一级 ViewModel 桥,其中模型被假定为值。因此,不支持ObservableObject内的分层更新自动

因此,将 TicTacToeModel 视为 ViewModel 部分,最简单也是最好的方法是从 class 更改模型,即 SquareModel code> 到 struct 如下

struct SquareModel {
    var status: Player = .empty
}

因此,SquareModel 中的任何更改都会更新 TicTacToeModel 中更新 View 的 board 属性。

关于swift - 使用嵌套模型更新 SwiftUI 中的 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60164458/

相关文章:

Swift:本地通知提前 1 小时安排

python 值列表,如何?

iOS SwiftUI - 使用 PhotosPicker 从图库中选择图像或视频

c# - 将 MVVM 与 CollectionViewSource 一起使用

c# - 无法转换 MS.Internal.NamedObject

ios - 如何在SwiftUI中汇总过滤后的核心数据?

iOS 15 SwiftUI TabView 标签栏外观不会在 View 之间更新

swift - CGDisplayCreateImage仅返回壁纸和任务栏

ios - 如何反转圆圈的绘制动画?

ios - 通过函数 prepare for segue 将数据传递给 ViewController 不起作用