Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用嵌套模型更新SwiftUI中的视图_Swift_Data Binding_Swiftui - Fatal编程技术网

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

使用嵌套模型更新SwiftUI中的视图,swift,data-binding,swiftui,Swift,Data Binding,Swiftui,我试图创建一个基本的tic-tac-toe游戏作为练习,但我无法根据存储游戏状态的模型(嵌套模型)更新我的视图,我的代码如下所示: TictoeModel存储SquareModel数组,SquareModel存储空、交叉或无状态 因此,每当用户按下一个空方块时,我想更新我的模型,并使用这个模型绘制“x”或“o”来更新我的视图 型号: final class TicTacToeModel: ObservableObject{ @Published var board = [SquareM

我试图创建一个基本的tic-tac-toe游戏作为练习,但我无法根据存储游戏状态的模型(嵌套模型)更新我的视图,我的代码如下所示:

TictoeModel存储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))
        }
    }
}
视图:


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

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

因此,考虑到
TicTacToeModel
作为视图模型的一部分,最简单的方法,也是最好的方法是将模型(即
SquareModel
)从
class
更改为
struct
,如下所示

struct SquareModel {
    var status: Player = .empty
}
因此,
SquareModel
中的任何更改都将更新更新视图的
TicTacToeModel
中的
board
属性

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()
        }))
    }
}
struct SquareModel {
    var status: Player = .empty
}