0

So I'm working on a quiz-app and I want to give the user an option screen before starting the quiz, where the user can choose which categories the quiz should have.

Its currently only working with 1 category at a time but I want to be able to concatenate the questionArrays when the user selects button in the option screen.

At this time the user selects a button and depending on the sender.tag an Int gets passed through the var called 'pickedCategory' which then decides which of the arrays to base the questions on. This happens in the prepare for segue:

    let selectedCategory = quizCategories[pickedCategory]
    secondVC.allQuestions = selectedCategory.questions

quizCategories is declared at the top:

    var quizCategories = [QuestionArray]() 

What I would like to do is have 4 buttons and whenever one is selected, concatenate an array to the selectedCategory

For instance, button 1 & 2 is selected, i.e. the user wants to have questions based on 2 categories. Resulting in something like this?

let selectedCategory = quizCategories[0].questions + quizCategories[1].questions

and if 3 buttons selected, add another quizCategories array to the final array etc etc

Please note, its not HOW to concatenate I'm looking for, its how to automatically do this depending on buttons selected..

This is my first question posted and I am very new to Swift.. hope I didn't confuse u guys.. thanks :)

  • 2
    Possible duplicate of [How do I concatenate or merge arrays in Swift?](https://stackoverflow.com/questions/25146382/how-do-i-concatenate-or-merge-arrays-in-swift) – Marc Nov 13 '17 at 13:38
  • I have read that, and its not what I'm looking for.. the concatenating part is ok, I more or less know the different types and how to use them.. but I'm not skilled enough to figure out how to get it done automatically depending on which buttons are selected.. – deadManMoonWalks Nov 13 '17 at 13:45
  • Sounds like you need a toggle button, create an @IBAction and then just trigger the concatenation depending on the toggle state of the button. – Marc Nov 13 '17 at 13:51
  • I have selectable buttons and linked IBActions. The triggering part is what I need help with... can you give me a specific example? As I mentioned in the question, I'm trying to get it to work with different combinations of buttons selected, and then pass that in to the prepare for segue – deadManMoonWalks Nov 13 '17 at 14:00

3 Answers3

0

You can track which button is selected and when you want to start quizz, concatenate the corresponding arrays.

Your code could look like this:

import UIKit

class QuizzSelection: UIViewController
{
  @IBAction func firstButtonAction(_ sender: Any)
  {
    firstButtonWasClicked()
  }

  @IBAction func secondButtonAction(_ sender: Any)
  {
    secondButtonWasClicked()
  }

  @IBAction func goForwardWithQuizz(_ sender: Any)
  {
    startQuizzWasClicked()
  }

  var isFirstCategorySelected = false
  var isSecondCategorySelected = false
  let firstCategoryQuestions = ["Question Cat 1"]
  let secondCategoryQuestions = ["Question Cat 2"]
  var emptyArrayOfQuestions = [String]()

  func firstButtonWasClicked()
  {
    if isFirstCategorySelected == true{
      isFirstCategorySelected = false
    } else{
      isFirstCategorySelected = true
    }
  }

  func secondButtonWasClicked()
  {
    if isSecondCategorySelected == true{
      isSecondCategorySelected = false
    } else{
      isSecondCategorySelected = true
    }
  }

  func startQuizzWasClicked()
  {
    if isFirstCategorySelected == true{
      emptyArrayOfQuestions += firstCategoryQuestions
    }
    if isSecondCategorySelected == true{
      emptyArrayOfQuestions += secondCategoryQuestions
    }
  }
}

EDIT

Improved code for six categories:

import UIKit

class QuizzSelection: UIViewController
{
  @IBAction func firstButtonAction(_ sender: Any)
  {
    firstButtonWasClicked()
  }

  @IBAction func secondButtonAction(_ sender: Any)
  {
    secondButtonWasClicked()
  }

  // Four mour button actions


  @IBAction func goForwardWithQuizz(_ sender: Any)
  {
    startQuizzWasClicked()
  }


  var wichCategoryAreSelected = [false, false, false, false, false, false] //six categories
  var arrayOfQuestions = [["Question 1 Cat 1","Question 2 Cat 1"], ["Question 1 Cat 2", "Question 2 Cat 2"], ...]
  var emptyArrayOfQuestions = [String]()


  func firstButtonWasClicked()
  {
    wichCategoryAreSelected[0] = !wichCategoryAreSelected[0]
  }

  func secondButtonWasClicked()
  {
    wichCategoryAreSelected[1] = !wichCategoryAreSelected[1]
  }

  func startQuizzWasClicked()
  {
    for i in 0...(wichCategoryAreSelected.count-1)
    {
      if wichCategoryAreSelected[i]
      {
        emptyArrayOfQuestions += arrayOfQuestions[i]
      }
    }
  }

}
standousset
  • 1,092
  • 1
  • 10
  • 25
  • The problem with this is, having lets say 6 different categories will result in a lot of if else statements, as you will have A LOT of different combinations of selected categories? – deadManMoonWalks Nov 13 '17 at 14:07
  • You're right. This answer was not aimed at being efficient but easily understood. And your question mentionned 4 categories. However, this code is very easily improvable: (i) the function firstButtonWasClicked() can be written in one line, (ii) startQuizzWasClicked() can also be written with a loop. – standousset Nov 13 '17 at 14:11
  • How do you create your button, manually or programmatically ? And how many do you thik you'll have maximum ? – standousset Nov 13 '17 at 14:12
0

Tags are not the best way to identify buttons, but I'll ignore that.

Don't use buttons, use UISwitches. Have a switch for each category.

Say you have a constant switchTagBase, with a value of 100:

let switchTagBase = 100

So the switch for your first category has a tag of 100, the next one has a tag of 101, etc.

You already have an array of categories, which is good.

Now, when it's time to build your array of selected questions, simply go through the categories, figure out which switches are on, and add in those categories

var selectedCategories = [QuestionArray]() 
for (index, array) in quizCategories.enumerated() {
  let thisTag = index + switchTagBase
  guard let thisSwitch = view.viewWithTag(thisTag),
    thisSwitch.isOn else { continue }
  selectedCategories += quizCategories[index]
}

(Note that you should really maintain an array of selection states based on the switches the user activates, and iterate through that array rather than looping through the switches directly, but in the interest of brevity I fetched switch states directly.)

Duncan C
  • 128,072
  • 22
  • 173
  • 272
0

What I would suggest is for each category button, keep track of which is selected (and even deselected if the user decides they don't want that category), by adding or removing from an array of categoryIDs. Then, once the "Done" button (or whatever final decision button is tapped), take the array of categoryIDs they selected, and flatMap over them to produce the ultimate array of questions.

let questions = categoryIDs.flatMap { quizCategories[$0].questions }

Now, you'd have your array of questions to present to the user. Use flatMap vs map, because you'd want to flatten the returned array of arrays into a single array.

BJ Miller
  • 1,536
  • 12
  • 16