Okay, was able to create a much smaller repro.
ContentView.swift:
import SwiftUI
struct ContentView: View {
@State var gridSize = 3
@State var selected = 0
@State var aCount = 0
@State var theToggle = true
var theTitle = "test"
@State var buttonBlank: Bool = true
var body: some View {
@State var gridCellArr = buildStructArray(theGridSize: gridSize)
HStack {
Button {
} label: {
Text("Commit Move")
}
.disabled(buttonBlank)
}
Grid(horizontalSpacing: 0, verticalSpacing: 0) {
ForEach(0..<gridSize, id: \.self) {
row in
GridRow {
ForEach(0..<gridSize, id: \.self) { col in
GeometryReader { proxy in
let index = row * gridSize + col
Button {
var theTuple = doSomethingElseOnClick(for: gridCellArr[index].index, myArray: gridCellArr)
gridCellArr[index].backCol = theTuple.myColor
gridCellArr[index].title = theTuple.myTitle
} label: {
Text(gridCellArr[index].title)
.font(.system(size: 36, weight: .heavy, design: .serif))
.frame(width: proxy.frame(in: .global).width,height: proxy.frame(in: .global).height)
}
.background(gridCellArr[index].backCol)
.border(Color.black)
.onAppear(perform: {
gridCellArr[index].xCoord = col
gridCellArr[index].yCoord = row
})
}
}
}
}
}
}
}
and the class + two other functions used:
import SwiftUI
import Foundation
@Observable class Cell: Identifiable {
let id = UUID()
var title: String = ""
var buttonToggled: Bool = false
var index: Int = 0
var xCoord: Int = 0
var yCoord: Int = 0
var backCol: Color = .gray
}
func buildStructArray(theGridSize: Int) -> [Cell] {
var myStructArray: [Cell] = []
let arraySize = (theGridSize * theGridSize) - 1
for i in 0...arraySize {
myStructArray.append(Cell())
}
for i in 0...arraySize {
myStructArray[i].index = i
}
return myStructArray
}
func doSomethingElseOnClick(for myIndex: Int, myArray: [Cell]) -> (myColor: Color, myTitle: String, myCommitButtonStatus: Bool) {
var theCommitButtonStatus: Bool = true
switch myArray[myIndex].title {
case "":
myArray[myIndex].title = "S"
theCommitButtonStatus = false
case "S":
myArray[myIndex].title = "O"
theCommitButtonStatus = false
case "O":
myArray[myIndex].title = ""
theCommitButtonStatus = true
default:
print("Something went wrong, try restarting the app")
}
if myArray[myIndex].title == "Button" {
print("it's a button")
}
var theColor: Color
if myIndex <= 7 {
let testIndex = myIndex + 1
print("\(myArray[testIndex].index)")
theColor = Color.green
} else {
let testIndex = myIndex - 1
print("\(myArray[testIndex].index)")
theColor = Color.blue
}
let theReturnTuple = (myColor: theColor, myTitle: myArray[myIndex].title, myCommitButtonStatus: theCommitButtonStatus)
return theReturnTuple
//return theColor
}
same issue with this as before:
the idea is, the board is built, all cells have a title of "" (blank) and Commit Move is disabled:
- the first time a button is clicked, its title should change to S and commit move is enabled
- second click, title changes to O, commit move is still enabled
- third click, title changes to "", commit move is disabled.
So a three-click rotation: "", "S", "O".
What i'm actually getting is a four click rotation:
- first click, button doesn't visibly change, but it thinks the title is now "S" and the commit move button is enabled
- second click, Button does visibly change to "S", title is STILL "S", and the commit move button is enabled
- third click, button visibly changes to "O", title is "O" and the commit move button is enabled
- fourth click, button visibly changes to "", title is "" and the commit move button is disabled
That's the cycle, but it gets weirder.
suppose on button 0, i leave it at "S" or "O".
Then i click on button 1. I get:
- first click: button does visibly change to "S", title is "S", and the commit move button is enabled
- second click: button visibly changes to "O", title is "O" and the commit move button is enabled
- third click: BOTH buttons change to "", title for both is "" and the commit move button is disabled
if I keep clicking, it goes back to a four-click cycle
if I move the buttonBlank @state var underneath body, the "all buttons blank" problem goes away, it's a three click cycle as I expect, but buttonBlank never changes so the commit move button is always disabled.
i am absolutely sure it's related to how I manipulate buttonBlank, because even if I have a line in the grid button click action block that just reads buttonBlank = false
or self.buttonBlank = false
I get the same behavior.
i am absolutely confused as to why though.