Search code examples
swiftfor-loopwaitfor-in-loop

Only continue within for loop if button was pressed


I have following setup: Classes A and B. Class A generates an array of settings of form [["SettingCategory"]]. Class B controls the view and contains 2 buttons and a submit button. I iterate through the array of settings using a for-in loop. The user can chose opt1/opt2 for each setting and then submit the choice. He will then be asked the second, third,.. setting. I am having troubles waiting for the user to submit his choice. My for loop just goes through all elements of the array without allowing any interactions. I do not need code, I would really appreciate a basic idea of how to do this properly.

Here is some simplified code:

class A{
   var settingCategories = [["Sound", "loud", "soft"], ["Brightness", "dark", "bright"]]
   
   for setting in settingCategories{
      if setting[0] == "Sound"{
         classB.showTheCategory(opt1: setting[1], opt2: setting[2])

         // here I want to wait for the user to choose "loud" or "soft" and then submit it.
         // I only want to continue, when the user submitted his choice!
         // my loop just iterates through all elements of the array and does not detect 
         // button taps.
      }
   }
}

class B{ // ViewController
   showTheCategory(opt1: String, opt2: String){
      // this ONLY generates and shows the buttons: opt1, opt2 and SUBMIT
   }
   detectButtonPressed(){
      // here I detect what button was pressed
   }
}

Because of my architecture I am not able to detect the pressed buttons within the showTheCategory function. I tried using a while loop within class A but I ended up getting an infinite loop. And I would not like to use a Timer since I do not know how long it takes the user to make and input. I looked up Notifications, but my for loop does not wait for properties to change, it just iterates through them quickly.


Solution

  • Here is some pseudo code

    // create an array to hold your answers
    var answers: [Answer] = []()
    // create an array to hold your questions
    var questions: [Question] 
    var currentQuestion: Question {
        didSet {
           // every time this property updates show the new question
           self.showQuestion(self.currentQuestion)
        }
    }
    
    init(questions: [Question]) {
       // store the questions
       self.questions = questions
       // pop your first questions from the list and assign it as the current question
       // this would also trigger its didSet method to display the question
       self.currentQuestion = self.questions.pop()
    }
    
    func showQuestion(_ question: Question) {
       // display question on screen
       questionLabel.text = question.text
       firstButton.title = question.firstOption
       secondButton.title = question.secondOption
    }
    
    func onButtonClick(sender: UIButton) {
       // user selected an answer, you can now store it and move to your next question. Here is how you can do it
       
       // create your answer and store it
       let answer = Answer(currentQuestion.text, answer: sender.title)
       self.answers.append(answer)
       // check if there is more questions in the list
       if self.questions.count > 0 {
          there is more questions so take one and show it the user
          self.currentQuestion = self.questions.pop()
       } else {
         // you have finished with all questions
         // you have successfully looped through all questions
         // and all user answers are now stored in your answers array
         // do with your answers whatever you need to. You're now done with asking questions :)
       }
    }
    

    This demonstrates the logic you could use to achieve what you're looking for. There is no need to implement for loops as you only need to wait for the user input. Once you receive the user input you store it and move to the next question and this is how you will eventually loop through all the questions. Hope it makes sense