iOS UI
Now to iOS. Here we use Swift UI to program our UI and like in Android a timer updates the state of the game every half a second.
struct BoardView: View {
@Binding var board: Board
var body: some View {
VStack(spacing: 2) {
ForEach(0..<Int(self.board.rows)) { rowIdx in
HStack(spacing: 2) {
ForEach(0..<Int(self.board.columns)) { columnIdx in
self.createCell(rowIdx: rowIdx, columnIdx: columnIdx)
}
}
}
}
}
private func createCell(rowIdx: Int, columnIdx: Int) -> some View {
let cell = self.board.cellAt(column: Int32(columnIdx), row: Int32(rowIdx))
if (cell.alive) {
return Rectangle()
.fill(Color.gray)
.frame(width: 10, height: 10)
}
return Rectangle()
.fill(Color.white)
.frame(width: 10, height: 10)
}
}
struct ContentView: View {
@ObservedObject var boardStore = BoardStore()
let timer = Timer.publish(every: 0.5, on: .main, in: .common).autoconnect()
var body: some View {
BoardView(board: $boardStore.board).onReceive(self.timer) { time in
self.boardStore.calculateNextGeneration()
}
}
}
Swift UI redraws the UI automatically based on the state of the application, so we need to make sure the game state is reflecting in the application state correctly.
class BoardStore: ObservableObject {
let columns: Int32 = 30
let rows: Int32 = 50
let objectWillChange = ObservableObjectPublisher()
var board: Board
init() {
self.board = Board.init(columns: columns, rows: rows)
let cells = BoardKt.cells(
"""
***_*
*____
___**
_**_*
*_*_*
""")
let cellsCentered = BoardKt.translatedTo(
cells, column: columns / 2 - 2, row: rows / 2 - 2 )
board.setCells(cellDefinitions: cellsCentered)
}
func calculateNextGeneration() {
self.board.calculateNextGeneration()
self.objectWillChange.send()
}
}