使用嵌套模型更新SwiftUI中的视图

时间:2020-02-11 08:12:09

标签: swift data-binding swiftui

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

TicTacToeModel存储一个SquareModel数组,SquareModel存储状态为空,叉或零。

因此,我想每次用户按下一个空的正方形来更新我的模型,并使用此模型绘制“ x”或“ o”来更新我的视图

型号:

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()
        }))
    }
}

注意:模型运行良好,并且可以正确存储所有属性

1 个答案:

答案 0 :(得分:0)

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

因此,将TicTacToeModel作为ViewModel的一部分,最简单的方法(最好是将SquareModel的模型从class更改为struct下面

struct SquareModel {
    var status: Player = .empty
}

因此,SquareModel中的任何更改都会更新board中的TicTacToeModel属性,从而更新视图。