Search code examples
swiftxcodebuttonsprite-kitskspritenode

Button function not handling the event properly when pressed?


struct Question {
    var Question : String!
    var Answers : [String]!
    var AnswerNumber : Int!
}

class LevelOne: SKScene {
    
    var button = Button()
    
    var buttons = [Button]()
    let Question_met = UILabel(frame: CGRect(x: 0.3, y: 0.3, width: 40, height: 21))
    
    var Questions = [Question]()
    
    var QNumber = Int()
    
    var buttonNames = [""]
    
    var AnsNumber = Int()
    
    let selectors:[Selector] = [#selector(handleButton1), #selector(handleButton2), #selector(handleButton3),#selector(handleButton4)]
    
    override func didMove(to view: SKView) {
        
        let background = SKSpriteNode(imageNamed: "background")
        background.position = CGPoint(x: self.size.width/2, y: self.size.height/2)
        background.zPosition = 0
        self.addChild(background)
        
        QuestionFunction()
        
        ButtonFuction()
         
        PickQuestion()
        
    }
    
    @objc func QuestionFunction(){
        
        Questions = [Question(Question: "What is a BMW ?", Answers: ["Bat","Cat","Vehicle","Pat"], AnswerNumber: 2),
        Question(Question: "What is a Boeing ?", Answers: ["Bat","Aircraft","Cat","Pat"], AnswerNumber: 1),
        Question(Question: "What is a Ant ?", Answers: ["Insect","Cat","Insect","Nate"], AnswerNumber: 2),
        Question(Question: "What is a Apple ?", Answers: ["Fruit","Cat","bat","Pat"], AnswerNumber: 0),
        Question(Question: "Where is london ?", Answers: ["UK","USA","France","Germany"], AnswerNumber: 0),
        Question(Question: "Where is New York ?", Answers: ["Canada","USA","France","Germany"], AnswerNumber: 2),
        Question(Question: "where is Berlin ?", Answers: ["UK","USA","Italy","Germany "], AnswerNumber: 3),
        Question(Question: "Where is Toronto ?", Answers: ["India","Africa","Canada","Norway"], AnswerNumber: 2),
        Question(Question: "Where is Rome ?", Answers: ["Japan","China","Italy","Ireland"], AnswerNumber: 2),
        Question(Question: "where is Chennai ?", Answers: ["India","Brazil","Swiss","Germany"], AnswerNumber: 0),]
        
        Question_met.frame = CGRect(x: 330, y: 70, width: 200, height: 21)
        Question_met.backgroundColor = UIColor.orange
        Question_met.textColor = UIColor.white
        Question_met.textAlignment = NSTextAlignment.center
        Question_met.text = "What caused Global Warming ?"
        self.view?.addSubview(Question_met)
        
    }
    
    @objc func ButtonFuction(){
        
        let stacView = UIStackView()
        stacView.spacing = 12
        stacView.distribution = .fillEqually
        stacView.axis = .horizontal
        stacView.translatesAutoresizingMaskIntoConstraints = false
        view!.addSubview(stacView)
        
        buttonNames = ["One","Two","Three","Four"]
        
        for name in buttonNames {
            button = Button()
            button.setTitle(name, for: .normal)
            stacView.addArrangedSubview(button)
            buttons.append(button)
        }
        
        for i in 0..<4{
            
            button.addTarget(self, action: selectors[i], for: .touchUpInside)
            
        }
    
        NSLayoutConstraint.activate([stacView.centerXAnchor.constraint(equalTo: view!.centerXAnchor),stacView.centerYAnchor.constraint(equalTo: view!.centerYAnchor),stacView.widthAnchor.constraint(equalToConstant: 350),stacView.heightAnchor.constraint(equalToConstant:70)])
        
    }
    
    @objc func PickQuestion(){
        
        if Questions.count > 0{
            QNumber = 0
            Question_met.text = Questions[QNumber].Question
            
            AnsNumber = Questions[QNumber].AnswerNumber
            
            for i in 0..<buttons.count{
                buttons[i].setTitle(Questions[QNumber].Answers[i], for: .normal)
            }
            Questions.remove(at: QNumber)
        }
        else {
            print("Done!")
        }
    }
    
    @objc func handleButton1() {
        
        if AnsNumber == 0 {
            PickQuestion()
            print("Correct!")
        }
        
        else {
            print("You are Wrong!!!")
        }
    }
    
    @objc func handleButton2(){
        
        if AnsNumber == 1 {
            PickQuestion()
            print("Correct!")
        }
        
        else {
            print("You are Wrong!!!")
        }
        
    }
    
    @objc func handleButton3(){
        
        if AnsNumber == 2 {
            PickQuestion()
            print("Correct!")
        }
        
        else {
            print("You are Wrong!!!")
            
        }
        
    }
    
    @objc func handleButton4(){
        
        if AnsNumber == 3 {
            PickQuestion()
            print("Correct!")
        }
        
        else {
            print("You are Wrong!!!")
        }
        
    }
}

The button action methods don't seem to be accurate in knowing which right answer button is being pressed while different number is assigned as answer for each question the methods seems to only move forward when pressing the last button.

Thank you in advance much appreciate the help.


Solution

  • Your problem is located in your ButtonFunction():

    for name in buttonNames {
        button = Button()
        button.setTitle(name, for: .normal)
        stacView.addArrangedSubview(button)
        buttons.append(button)
    }
    
    for i in 0..<4{
        
        button.addTarget(self, action: selectors[i], for: .touchUpInside)
        
    }
    

    In the second loop, you do not initialize the button variable, so this is always the fourth button.. Better join this code in only one loop like so:

    for i in 0..<4{
        button = Button()
        button.setTitle(buttonNames[i], for: .normal)
        stacView.addArrangedSubview(button)
        buttons.append(button)
        button.addTarget(self, action: selectors[i], for: .touchUpInside)
    }
    

    Beyond this solution some advices to your coding style:

    • for convenience and better readability, function names and variable names should start with a lower letter
    • declare your variables in the smallest possible scope.
      • button, buttonNames and selectors are only used in ButtonFunction(), so these should be declared there.
      • declaration of button should in fact be in the for loop only. This way, the compiler would have told you, that button is unknown in your second loop and you would have seen the problem on your own ;)