How to make UIButton unclickable after touched one time and hide and unhide button? - swift

Viewed 713

I have made a quiz app. 1) I want the buttons with the answers to be unclickable if it is touched one time per question.2) Also i want to hide and unhide the "next question" button everytime the user moves to the next answer. For example Question 1. next question button is hidden --> user touches an answer --> all answer buttons become unclickable ( 1) i want to do this)--> next question button unhidden ( 2) i want to do this).

import UIKit

struct Question {
    var Question: String!
    var Answers: [String]!
    var Answer: Int!

    init(item: [String: Any])
    {
        self.Question = item["Question"] as? String
        self.Answers = item["Answers"] as? [String]
        self.Answer = item["Answer"] as? Int
    }
}

class LittleTestViewController: UIViewController {

    //MARK: Properties
    @IBOutlet weak var questionLabel: UILabel!
    @IBOutlet var buttons: [UIButton]!
    @IBOutlet weak var Next: UIButton!

    var Questions = [Question]()
    var QNumber = Int()
    var answerNumber = Int()
    var score = Int()

    override func viewDidLoad() {
        super.viewDidLoad()
        Hide()
        jsonParsingQuestionsFile()
        pickQuestion()
    }

    func jsonParsingQuestionsFile ()
    {
        if let path = Bundle.main.path(forResource: "data", ofType: "json")
        {
            if let array = (try? JSONSerialization.jsonObject(with: Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe), options: JSONSerialization.ReadingOptions.allowFragments)) as? [[String : Any]]
            {
                for item in array
                {   
                    self.Questions.append(Question(item: item))
                }
            }
        }
    }

    func pickQuestion ()
    {

        if Questions.count > 0 {
            QNumber = 0

            questionLabel.text = Questions[QNumber].Question

            answerNumber = Questions[QNumber].Answer

            for i in 0..<buttons.count{
                buttons[i].setTitle(Questions[QNumber].Answers[i], for: UIControlState.normal)
            }
            Questions.remove(at: QNumber)
        }
        else
        {
           let alert = UIAlertController(title: "Σκόρ", message: "Απάντησες σωστάς τις \(score) ερωτήσεις από τις 3", preferredStyle: UIAlertControllerStyle.alert)
            alert.addAction(UIAlertAction(title: "Μενού", style: UIAlertActionStyle.default, handler: { action in
                self.navigationController?.popToRootViewController(animated: true)
            }))
            self.present(alert, animated: true, completion: nil)
        }
    }

    func Hide()
    {
        Next.isHidden = true
    }

    func Unhide()
    {
        Next.isHidden = false
    }

    @IBAction func bt1(_ sender: UIButton) {
        Unhide()
        if answerNumber == 0 {
            sender.backgroundColor = UIColor.green
            score+=1
        }
        else
        {
            sender.backgroundColor = UIColor.red
        }
    }
    @IBAction func btn2(_ sender: UIButton) {
        Unhide()
        if answerNumber == 1 {
            sender.backgroundColor = UIColor.green
            score+=1
        }
        else
        {
            sender.backgroundColor = UIColor.red
        }
    }
    @IBAction func btn3(_ sender: UIButton) {
        Unhide()
        if answerNumber == 2 {
            sender.backgroundColor = UIColor.green
            score+=1
        }
        else
        {
            sender.backgroundColor = UIColor.red
        }
    }
    @IBAction func btn4(_ sender: UIButton) {
        Unhide()
        if answerNumber == 3 {
            sender.backgroundColor = UIColor.green
            score+=1
        }
        else
        {
            sender.backgroundColor = UIColor.red
        }
    }

    @IBAction func Next(_ sender: Any)
    {
        pickQuestion()
    }

}
2 Answers

To make a button unclickable:

myAnswerButton.isEnabled = false

To hide your next question button:

myNextQuestionButton.isHidden = true

To unhide your next question button:

myNextQuestionButton.isHidden = false

Define you buttons like:

@IBOutlet weak var btn1: UIButton!
@IBOutlet weak var btn2: UIButton!
@IBOutlet weak var btn3: UIButton!
@IBOutlet weak var btn4: UIButton!

Create a function to disable all buttons:

private func disableAllAnswerButtons() {
    btn1.isUserInteractionEnabled = false
    btn2.isUserInteractionEnabled = false
    btn3.isUserInteractionEnabled = false
    btn4.isUserInteractionEnabled = false
}

You'll need to enable again with another function:

private func enableAllAnswerButtons() {
    btn1.isUserInteractionEnabled = true
    btn2.isUserInteractionEnabled = true
    btn3.isUserInteractionEnabled = true
    btn4.isUserInteractionEnabled = true
}

Disable them in the unhide function:

func Unhide()
    {
        Next.isHidden = false
        disableAllAnswerButtons()
    }

Enable them again when next question button is pressed:

 @IBAction func Next(_ sender: Any)
    {
        pickQuestion()
        enableAllAnswerButtons()
    }

.isHidden: will set your button visible or invisible (wont handle event or anything its like its not there)

.isEnable: will set your button to normal state or normal state but a bit transparent (alpha 0.7+/-) and wont be clickable (wont pass touch to super view)

PD: recommend u using "guard" instead of nested if

func jsonParsingQuestionsFile ()
    {
        if let path = Bundle.main.path(forResource: "data", ofType: "json")
        {
            if let array = (try? JSONSerialization.jsonObject(with: Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe), options: JSONSerialization.ReadingOptions.allowFragments)) as? [[String : Any]]
            {
                for item in array
                {   
                    self.Questions.append(Question(item: item))
                }
            }
        }
    }

to this:

func jsonParsingQuestionsFile ()
{
    guard let path = Bundle.main.path(forResource: "data", ofType: "json"),
          let array = (try? JSONSerialization.jsonObject(with: Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe), options: JSONSerialization.ReadingOptions.allowFragments)) as? [[String : Any]] else{
        return
    }

    for item in array
    {   
       self.Questions.append(Question(item: item))
    }
}

Also

Your IBActions of ur buttons are the same, you should use the same for every button action, just link all the button actions to the same IBAction code in ur controller. If needed (not ur case) use button tags to distinct witch button was pressed.

Related