skip to Main Content

I’m making a simple minesweeper app. At the bottom I have a toolbar with a button to toggle whether the game is in "flagging mode". I have two possible images for the button itself- one for when flagging mode is enabled and another for when it isn’t- and I’d like it to switch between the two when it’s clicked.

Essentially, I want to make a toggle with custom images for on/off.

However, the code I have below isn’t updating the image and I can’t figure out why.

GameView() // the content view
    .environmentObject(game)
    .padding()
    .toolbar {
        ToolbarItemGroup(placement: .bottomBar) {
            Button(action: game.toggleFlagMode) {
                if game.isFlagMode {
                    Image("flag toggle on")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                }
                else {
                    Image("flag toggle off")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                }
            }
            Button("Reset") {
                game.resetBoard()
            }
        }
    }

And my Game.swift file (shortened to what’s relevant)

import Foundation


class Game: ObservableObject {
    
    @Published var isFlagMode: Bool
    [ ... ]

    
    init(from settings: GameSettings) {
        self.isFlagMode = false
        [ ... ]
    }

    // toggle whether the game is in mode to flag cells
    func toggleFlagMode() {
        self.isFlagMode = !self.isFlagMode
    }

Flag mode is correctly being toggled by the button. That is- when I click it to enable it’s properly flagging cells when clicked. So I think the issue is with the View and not Game itself.

EDIT (Solution):

I had this code in my main MinesweeperApp.swift file. I placed the toolbar code into a different view that MinesweeperApp was calling and it started working.

3

Answers


  1. A couple of mistake you have:

    In the viewModel you could just:

    func toggleFlagMode() {
            self.isFlagMode.toggle()
        }
    

    In the view:

     .environmentObject(game)
                .padding()
                .toolbar {
                    ToolbarItemGroup(placement: .bottomBar) {
                        Button(action: game.toggleFlagMode) {
                            Image(systemName: game.isFlagMode ? "square.and.arrow.up" : "pencil")
                                    .resizable()
                                    .aspectRatio(contentMode: .fit)
                                    .foregroundColor(.red)
                        }
                        Button("Reset") {
                            game.resetBoard()
                        }
                    }
                    
                }
    

    If you are using imported images(from Assets) remember to remove the systemName.

    enter image description here

    Login or Signup to reply.
  2. The simplest way to handle this is with an @State variable. In other words it’s a variable that updates the view when the state changes. For example.

    @State var isFlaggingModeEnabled = false 
    
    var body: some View {
         Button(action: { isFlaggingModeEnabled.toggle() }, 
                label: {
                    switch isFlaggingModeEnabled {
                        case true:
                            // Your image for when enabled.
                        default:
                            // Your image for when disabled. 
                    }         
         }
    }
    
    Login or Signup to reply.
  3. GameView() // the content view
    .environmentObject(game)
    .padding()
    .toolbar {
        ToolbarItemGroup(placement: .bottomBar) {
            Button(action: {
            game.toggleFlagMode()
        }) {
            Image(game.isFlagMode ?  "poire" : "pomme")
                .resizable()
                .aspectRatio(contentMode: .fit)
        }
            Button("Reset") {
                game.resetBoard()
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search