简体   繁体   中英

How to share data between class and view in SwiftUI

I'm trying to build an 2048 game to learn SwiftUI but I'm stuck. I have three classes, Game, Board and Tiles. Game has a variable that contains an instance of Board and board has a variable that contains a matrix of Tiles.

In the same way, I have three views, ContentView.swift, BoardView.swift and TilesView.swift

In the view ContentView.swift I initialize Game like this :

@ObservedObject var game = Game()
...
Blocks(board: self.game.board)

Then in BoardView.swift :

@ObservedObject var board: Board
... Loop ...
TileView(value: self.board.board[y][x].value)
...
.gesture(
    DragGesture()
        .onChanged({ value in
             let direction = self.board.gestureToDirection(startLocation: value.startLocation, location: value.location)
             self.board.move(direction: direction)
        })
)

And in TileView.swift :

@State var value: Int = 0;

Game.swift :

class Game: ObservableObject {

    @Published var board = Board()

}

Board.swift :

class Board: ObservableObject {

    @Published var board: [[Tile]] = []
    /* Here is the logic of the game, when a gesture is triggered in ContentView.swift, I call a function to move the tiles */
}

Tiles.swift :

class Tile: ObservableObject {
    @Published var coords: Coords
    @Published var value: Int
}

My problem is that when I drag on the screen, the board doesn't change, and I have the feeling that the content of my board is not the same in my different files ...

How can I share data between view and classes ?

Thanks.

I believe this is because the @Published changes are not published through the board: [[Tile]] array. I have run into similar issues, here for example.

One thing to try would be to give each Tile object a reference back to the Board that owns it, and manually trigger the board's objectWillChange when changes need publishing.

I would recommend the following changes (scratchy):

1) Make a model, Tile , a value type

struct Tile {
    var coords: Coords
    var value: Int
}

2) Make a TileView present, as it sounds, a Tile , and give it a model as binding (@State is for internal usage, take a habit to give it private )

struct TileView: View {
   @Binding var model: Tile
   ...

3) make a bind between views

TileView(model: self.$board.board[y][x])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM