Radio Buttons not Working

Hello I am trying to implement use of Radio buttons. After days of trying to get the values of my radio buttons (that is to see which one is checked and save value) I have had no success:


Here is my code:


var qValueNumbers = [0]
    let totalSum = Int()
    @IBAction func calcGroupScore(_ sender: NSButton) {
        answerItem = ""
       
            for item in results {
                if let record = item.value(forKey: "answer") as? String {
                    answerItem.append(record)
                    answerLabel.stringValue = answerItem
                    print ("Answer is \(answerItem)")
               
                   
                if let record = item.value(forKey: "qValue") as? String, var theValue = Int(record) {
   //                groupScoreLabel.stringValue = qValueItem
                 
           
          print ("qValueNumbers before append", qValueNumbers)

                    func getScore (){
                   
                  if (oneRadioButton != nil)   && distractor1 == answerItem {
                        print("button1 Selected")
                       qValueNumbers.append(theValue)
                    }
                       
                    if (twoRadioButton != nil) && distractor2 == answerItem {
                            print("button2 Selected")
                        qValueNumbers.append(theValue)
                  }
                       
                    if (threeRadioButton != nil) && distractor3 == answerItem {
                            print("button3 Selected")
                        qValueNumbers.append(theValue)
                  }
                       
                    if (fourRadioButton != nil) && distractor4 == answerItem {
                        print("button4 Selected")
                        qValueNumbers.append(theValue)
                    }
                    if (fiveRadioButton != nil) && distractor5 == answerItem {
                        print("button5 Selected")
                        qValueNumbers.append(theValue)
                        }
                       
                    else{
//                       qValueNumbers.append(0)
                        print ("The value of qValue is \(theValue)")
                    }
            }
                    getScore()
                    qValueNumbers.append(theValue)
                    let totalSum = qValueNumbers.reduce(0, +)
                      print ("qValue is \(theValue)")
                      print ("qValueNumbers after append", qValueNumbers)
                      print ("Total is \(totalSum)")
                      print ("Group score is \(totalSum)")
                   
                }
                
        }
       
    }


Here is my log output:


Answer is 3

qValueNumbers before append [0, 1530, 2650]

The value of qValue is 2650

qValue is 2650

qValueNumbers after append [0, 1530, 2650, 2650]

Total is 6830

Group score is 6830


Here is the problem:


Whether or not a button is selected the "qValue" is still appended to qValueNumbers". If a radio button between 1 and 5 is selected and that button is the correct answer, then the qValue should be appended. As of now regardless of whether the checked button matches the correct answer a qValue is still appended instead of "0".


Any help will nbe appreciated.

Answered by Claude31 in 400101022

Great.


You're right, to begin, it may be good to write a bit verbose but easy to understand code.

But, in that case, it is better to make names very explicit, such as recordAnswer vs record only.


Clearly, if distriX were not defined, it could never match.

So, that answers a previous question: does buttonX selected ever gets printed ?

If no (that was the case), that means that your test failed for some reason (the one you found).


Anyway, good continuation you can now close the thread.

As of now regardless of whether the checked button matches the correct answer a qValue is still appended instead of "0".


That is the result of line 51: whatever the test results, you append a qValue (The value of qValue is 2650) which was not reset to zero in else of line 45.

To get what you want, uncomment line 46

qValueNumbers.append(0)

and remove line 51, because you did the append in getScore().

You could also improve your code as follows:


- replace the declarations of 5 radioButtons with an IBOutletCollection:

@IBOutlet var radioButtons: [UIButton]!


To do so:

- remove all connections of radioButtons to their IBOutlet

- remove the IBOutlet declarations (as @IBOutlet var oneRadioButton: UIButton!)

- declare the IBOutletCollection in code as in line 1

- connect each radio button in IB to this IBOutlet

- Need to do it in right order so that first button (radio1) in the first in array


Put distractorX in an array ( in viewDidLoad if it is static data, or in place where you did set the distractor if it is dynamic data):

var distractors: [String]  = []  


What you do with answerItem is not clear.

line 8, you append the record.

But, can you append multiple records ?

Then, are you sure any distractor will match ?

=> You should be clear on this


It is not a very good practice to use the same record name for different uses.

I edited the names in the following

I would also get the getScore func out of the loop, for better readability.


Now your code becomes:



@IBOutlet var radioButtons: [UIButton]!
var distractors: [String]   // Need to feed with former disctractor1 to distractor5

var qValueNumbers = [0]
let totalSum = Int()

func getScore() -> Int {

    if distractors.count != radioButtons.count {                // safety check
          print("radioButtons and distractors don't match")
          return
     }
    for i in 0 ..< radioButtons.count  {
          if (radioButtons[i] != nil) && distractors[i] == answerItem {
            print("button \(i+1) Selected. distractor is \(distractors[i])")
            qValueNumbers.append(theValue)
            return  // We found one, no need to continue testing for the following
        }
    }
    print("no button Selected or matching answer")
    qValueNumbers.append(0)
}

@IBAction func calcGroupScore(_ sender: NSButton) {
    answerItem = ""

    for item in results {
        if let recordAnswer = item.value(forKey: "answer") as? String {
            // MAYBE you need to set answerItem HERE
            answerItem.append(recordAnswer)
            // THEN this append could be replaced by
            // answerItem = recordAnswer

            answerLabel.stringValue = answerItem
            print ("Answer is \(answerItem)")
       
            if let recordValue = item.value(forKey: "qValue") as? String, var theValue = Int(recordValue) {
                //                groupScoreLabel.stringValue = qValueItem
           
                print ("qValueNumbers before append", qValueNumbers)
           
                getScore()
                //                qValueNumbers.append(theValue)
                let totalSum = qValueNumbers.reduce(0, +)
                print ("qValue is \(theValue)")
                print ("qValueNumbers after append", qValueNumbers)
                print ("Total is \(totalSum)")
                print ("Group score is \(totalSum)")
            }
       
        }
    }          // end of for loop

}

You are not showing very important parts of your code, th declarations of `oneRadioButton`, `twoRadioButton`, ...


I guess they are IBOutlets of type `NSButton!`.


If my guess is right, the expression `oneRadioButton != nil` does not test whether the radio button is selected, but test if the outlet is surely connected.


You may need to modify your `getScore()` as follows:

                    func getScore() {
                        if oneRadioButton.state == .on   && distractor1 == answerItem {
                            print("button1 Selected")
                            qValueNumbers.append(theValue)
                        }
                        if twoRadioButton.state == .on   && distractor2 == answerItem {
                            print("button2 Selected")
                            qValueNumbers.append(theValue)
                        }
                        if threeRadioButton.state == .on && distractor3 == answerItem {
                            print("button3 Selected")
                            qValueNumbers.append(theValue)
                        }
                        if fourRadioButton.state == .on  && distractor4 == answerItem {
                            print("button4 Selected")
                            qValueNumbers.append(theValue)
                        }
                        if fiveRadioButton.state == .on  && distractor5 == answerItem {
                            print("button5 Selected")
                            qValueNumbers.append(theValue)
                        }
                        print ("The value of qValue is \(theValue)")
                    }


I am not sure other parts of your code would work as you expect or not, but this issue

Whether or not a button is selected the "qValue" is still appended to qValueNumbers".

will be fixed with the changes above.

Sure.


In fact, wlionel, why did you change the code from your previous thread:

  if oneRadioButton.state == .on && distractor1 == answerItem {


Did you have crash with this ?


then, that would mean you have another problem elsewhere

Hello Claude31:


I have learned that it's always good to sleep on a problem. That's seem to create awareness of solutions.


I realized that i was comparing the wrong values:

if oneRadioButton.state == .on   && distractor1 == answerItem {

That would never give me the correct result. I had to define values matching "answerItem(s)" as so:

var distr1: String = "1"
var distr2: String = "2"
var distr3: String = "3"
var distr4: String = "4"
var distr5: String = "5"

Then the full code that works was as follows:


var qValueNumbers = [0]
    let totalSum = Int()
    var distr1: String = "1"
    var distr2: String = "2"
    var distr3: String = "3"
    var distr4: String = "4"
    var distr5: String = "5"
    @IBAction func calcGroupScore(_ sender: NSButton) {
        answerItem = ""
       
            for item in results {
                if let record = item.value(forKey: "answer") as? String {
                    answerItem.append(record)
                    answerLabel.stringValue = answerItem
                    print ("Answer is \(answerItem)")
             if let record = item.value(forKey: "qValue") as? String, var theValue = Int(record) {
   //                groupScoreLabel.stringValue = qValueItem
                 
           
          print ("qValueNumbers before append", qValueNumbers)

                    func getScore (){
                   
                  if (oneRadioButton.state == .on  && distr1 == answerItem) {
                        print("button1 Selected")
                       qValueNumbers.append(theValue)
                    }
                       
                    else if (twoRadioButton.state == .on && distr2 == answerItem) {
                            print("button2 Selected")
                        qValueNumbers.append(theValue)
                  }
                       
                    else if (threeRadioButton.state == .on && distr3 == answerItem) {
                            print("button3 Selected")
                        qValueNumbers.append(theValue)
                  }
                       
                    else if (fourRadioButton.state == .on && distr4 == answerItem) {
                        print("button4 Selected")
                        qValueNumbers.append(theValue)
                    }
                    else if (fiveRadioButton.state == .on && distr5 == answerItem) {
                        print("button5 Selected")
                        qValueNumbers.append(theValue)
                        }
                       
                    else{
                       qValueNumbers.append(0)
                        print ("The value of qValue is \(theValue)")
                    }
            }
                    getScore()
                    let totalSum = qValueNumbers.reduce(0, +)
                      print ("qValue is \(theValue)")
                      print ("qValueNumbers after append", qValueNumbers)
                      print ("Total is \(totalSum)")
                      print ("Group score is \(totalSum)")
                            }
                        }
                    }

My "getScore" function may be simplistic and could be refined but I'm learning. [I also Noted that OOper had also suggested the chande in the function that worked in my last coding]


Log after four taps on button with second and third taps selecting the incorrect answers:


Answer is 3

qValueNumbers before append [0, 0, 2080, 0]

button3 Selected

qValue is 3850

qValueNumbers after append [0, 0, 2080, 0, 3850]

Total is 5930

Group score is 5930


Thanks Guys!

Accepted Answer

Great.


You're right, to begin, it may be good to write a bit verbose but easy to understand code.

But, in that case, it is better to make names very explicit, such as recordAnswer vs record only.


Clearly, if distriX were not defined, it could never match.

So, that answers a previous question: does buttonX selected ever gets printed ?

If no (that was the case), that means that your test failed for some reason (the one you found).


Anyway, good continuation you can now close the thread.

Radio Buttons not Working
 
 
Q