0

In my Swift iOS app, I have implemented an UIAlertController to display a message with "Yes" and "No" buttons. The "Yes" button correctly resets the game, but when you tap the "No" button, the alert controller does not dismiss as expected (I want to navigate back to SecondViewController). This is my code right now for SecondViewController (this is where I want to navigate back to)

import UIKit

class SecondViewController: UIViewController {

    let TO_GAME_SCREEN = "toGameScreen"
    var playAgainstComputer = GameSettings.shared.playAgainstComputer
    var logicAndRules = LogicAndRules()
    
  

    @IBOutlet weak var txtPlayerOne: UITextField!
    @IBOutlet weak var txtPlayerTwo: UITextField!
    @IBOutlet weak var btnNavigate: UIButton!
    @IBOutlet weak var btnPlayNPC: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
                
    }
    
    override func viewDidAppear(_ animated: Bool) {
        txtPlayerOne.text = ""
        txtPlayerTwo.text = ""
    }
    
    @IBAction func btnNavigate(_ sender: UIButton) {
        GameSettings.shared.playAgainstComputer = false
        guard let playerOneName = txtPlayerOne.text, !playerOneName.isEmpty, !isNumeric(input: playerOneName) else {
                // Visa ett felmeddelande om användaren skriver ett nummer
                showAlert(message: "Invalid player name for Player 1")
                return
            }
        guard let playerTwoName = txtPlayerTwo.text, !playerTwoName.isEmpty, !isNumeric(input: playerTwoName) else {
              // Visa ett felmeddelande om användaren skriver ett nummer
              showAlert(message: "Invalid player name for Player 2")
              return
          }

        performSegue(withIdentifier: TO_GAME_SCREEN, sender: self)
    }
    
    func isNumeric(input: String) -> Bool {
        return Int(input) != nil
    }

    func showAlert(message: String) {
        let alertController = UIAlertController(title: "Error", message: message, preferredStyle: .alert)
        let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
        alertController.addAction(okAction)
        present(alertController, animated: true, completion: nil)
    }
    
    
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        
        if segue.identifier == TO_GAME_SCREEN {
            
            if let destinationVC = segue.destination as? GameViewController {
                
                guard let txtPlayerOne = txtPlayerOne.text else {return}
                guard let txtPlayerTwo = txtPlayerTwo.text else {return}
                
                destinationVC.logicAndRules.playerOneName = txtPlayerOne.isEmpty ? "X" : txtPlayerOne
                destinationVC.logicAndRules.playerTwoName = txtPlayerTwo.isEmpty ? "O" : txtPlayerTwo
            }
        }
    }
    
    
    @IBAction func btnPlayNPC(_ sender: UIButton) {
        GameSettings.shared.playAgainstComputer = true
        txtPlayerOne.text = "Player"
        txtPlayerTwo.text = "Computer"
        performSegue(withIdentifier: TO_GAME_SCREEN, sender: self)
    }
    
}
    

And this is my code in GameViewController where I actually have my alertMessage:

import UIKit


class GameViewController: UIViewController { // hanterar användargränssnittet
    
    // All my outlets
    @IBOutlet weak var turnSign: UILabel!
    @IBOutlet var buttons: [UIButton]!
    
   
    let playAgainstComputer = GameSettings.shared.playAgainstComputer
    var logicAndRules = LogicAndRules()
    
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        logicAndRules.boardArray = ["", "", "", "", "", "", "", "", ""]
        
        if (logicAndRules.currentPlayer == 1) {
            turnSign.text = logicAndRules.playerOneName
        } else {
            turnSign.text = logicAndRules.playerTwoName
        }
    }
    
    func switchPlayers() {
        logicAndRules.switchPlayers()
    }
    
    
    func resetGame() {
        
        logicAndRules.boardArray = ["", "", "", "", "", "", "", "", ""]
        
        for button in buttons {
            button.setTitle("", for: .normal)
            button.isEnabled = true
        }
        logicAndRules.currentPlayer = 1
        turnSign.text = logicAndRules.playerOneName
    }
    
    func makeComputerMove() {
        var emptySpots = [Int]()
        for (index, value) in logicAndRules.boardArray.enumerated(){
            if value.isEmpty{
                emptySpots.append(index)
            }
        }
        if let randomIndex = emptySpots.randomElement(){
            let buttonToPress = buttons[randomIndex]
            buttonTapped(buttonToPress)
        }
    }
    
    func playAgainstNPC() {
        logicAndRules.playAgainstNPC()
        makeComputerMove()
    }
    
    func myAlertMessage(winnerMessage: String){
        let crossesText = "Crosses: \(logicAndRules.countPLayer1)"
        let noughtsText = "Noughts: \(logicAndRules.countPlayer2)"
        
        let messageText = "Do you wanna play again?\n\n\(crossesText)\n\(noughtsText)"
        
        let myAlertController = UIAlertController(title: winnerMessage, message: messageText, preferredStyle: .alert)
        
        let yesAction = UIAlertAction(title: "Yes", style: .default){_ in
            self.resetGame()
        }
        
        let noAction = UIAlertAction(title: "No", style: .cancel){_ in
            self.dismiss(animated: true)
           
        }
        
        myAlertController.addAction(yesAction)
        myAlertController.addAction(noAction)
        
        present(myAlertController, animated: true, completion: nil)
    }

    /**
     In this function I want to set a  title on a button and then switch turn when a button is pressed
     All the buttons are attached to this function so that "let index" will include same terms for all my buttons
     **/
    @IBAction func buttonTapped(_ sender: UIButton) {
        let index = sender.tag
        if logicAndRules.boardArray[index] == ""{
            if logicAndRules.currentPlayer == 1 {
                logicAndRules.boardArray[index] = "X"
                sender.setTitle("X", for: .normal)
            } else {
                logicAndRules.boardArray[index] = "O"
                sender.setTitle("O", for: .normal)
            }
            
            sender.setTitle(logicAndRules.boardArray[index], for: .normal)
            
            logicAndRules.switchPlayers()
            
            if logicAndRules.currentPlayer == 1 {
                turnSign.text = logicAndRules.playerOneName
            } else {
                turnSign.text = logicAndRules.playerTwoName
            }
            
            if let winnerMessage = logicAndRules.checkForWinner() {
                logicAndRules.winner = winnerMessage
                myAlertMessage(winnerMessage: winnerMessage)
            }
        } else if !logicAndRules.boardArray.contains("") {
            myAlertMessage(winnerMessage: "It's a tie!")
        }
        if GameSettings.shared.playAgainstComputer && logicAndRules.currentPlayer == 2 {
            playAgainstNPC()
        }
        
    }
}

I have attempted to dismiss the alert controller using

myAlertController?.dismiss(animated: true, completion: nil)

, but this does not work. the alert controller remains on the screen, and the expected behavior of dismissing the alert when the "No" button is pressed is not being achieved.

5
  • dismiss is only going to work if the view controller was shown with present. How are you displaying GameViewController? It looks like a segue is being used. How is it setup? Commented Sep 25, 2023 at 17:43
  • Yes I am using a UIStoryboard segue to navigate from SecondViewController to GameViewController and the GameViewController Is shown as Push not with present. Is it possible to do this another way without showing it with present? Commented Sep 25, 2023 at 20:16
  • Maybe I can use unwind segue? @HangarRash Commented Sep 25, 2023 at 20:22
  • Replace the use of dismiss with popViewController on the navigation controller. Commented Sep 25, 2023 at 20:28
  • Thank you so much, now it works fine! @HangarRash Commented Sep 26, 2023 at 7:54

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.