Swift – Make a Trivia Quiz Game
In this Swift quiz app tutorial we will look at making a iOS quiz. It might sound complicated and scary at first, but it’s actually quite simple. Lets start off by making a single view application. Our end will result will be a quiz app like this:
Setting up the User Interface
To start off create a new single view application in XCode. Then head over to the Main.storyboard and layout out either as follows, or similar if you wish to change the design. Take the following steps to do this:
- Change the background color to a light grey, we will change this later
- Add a UITextField to the top for the question. Set the font size to 36 and text to white.
- Add a UIView to the center, set the background color to white
- In this UIView add four UIButtons which will contain each answer. Set the font size to 30.
- Under these buttons ad a UILabel, set the font size to 17. This will contain your progress for the quiz.
Now these are setup lets connect up the interface to the code. Go to the assistant editor in the top right to split the view, so we have the ViewController.Swift code. For each step below control click on each element in the storyboard, and drag it to the code to connect it up.
- Connect the top question label up as an Outlet, name it lblQuestion
- For each answer button connect them up as an Outlet, naming them Answer0 – 4, with answer 0 being the top button.
- Connect up the progress label (x /x) as an Outlet, naming it lblProgress
- For each answer button connect it up as an action this time, naming it submitAnswer0 – 4, with answer 0 being the top button.
With your view controller connected up now your code will look like the following:
class ViewController: UIViewController { @IBOutlet var lblQuestion: UITextView! @IBOutlet var answer0: UIButton! @IBOutlet var answer1: UIButton! @IBOutlet var answer2: UIButton! @IBOutlet var answer3: UIButton! @IBOutlet var lblProgress: UILabel! override func viewDidLoad() { super.viewDidLoad() } @IBAction func submitAnswer0(_ sender: Any) { } @IBAction func submitAnswer1(_ sender: Any) { } @IBAction func submitAnswer2(_ sender: Any) { } @IBAction func submitAnswer3(_ sender: Any) { } }
Now we have our layout setup, we need to also do this for the Results screen, then we can start coding. We are going to setup the results screen to look like below with these steps:
- Drag a label to the center, set the font size to 40. This will be a message that changes depending on how well the user went in the quiz.
- Drag a label under this, set the font size to 17. This will let the users know how many answers they got correct in the quiz.
With this done, before we connect it up to code we need to connect both screens up. This will be done with a segue, select the little yellow square at the top of the first view controller that holds the questions. Then holding the control key drag and drop this to our Results screen, and select “Show” from the dropdown under Manual Segue. Next select the segue . In the top right under the attributes inspector set the identifier to “sgShowResults”.
Now we have set this up to show the results screen, go to File->New->File. Select CocoaTouch Class. In the next screen name the class ResultsViewController and make sure the Subclass of is UIViewController. Then go next and create the file. Go back to the Main.Storyboard, and select the Results screen we just created, at the top right select the identity inspector and change the class to ResultsViewController.
Lets connect it up, go to the assistant editor in the top right to split the view, so we have the ResultsViewController.Swift code. For each step below control click on each element in the storyboard, and drag it to the code to connect it up.
- Connect the top label up as an outlet, name it lblTitle
- Connect the bottom label up as an outlet, name it lblResults
You will now have the following in ResultsViewController.Swift
@IBOutlet var lblTitle: UILabel! @IBOutlet var lblResults: UILabel!
Coding the Quiz App
Now we have set it all up, lets get around to coding the app. Go back to the ViewController.swift as this presents the quiz questions to the user. And add the following in above viewDidLoad:
struct Question { let question: String let answers: [String] let correctAnswer: Int } var questions: [Question] = [ Question( question: "What is 1+1?", answers: ["1", "2", "3", "4"], correctAnswer: 1), Question( question: "Have you subscrbed to Seemu Apps", answers: ["Yes", "No", "I will", "No Thanks"], correctAnswer: 0), Question( question: "What is the Capital of Australia?", answers: ["Sydney", "Melbourne", "Adelaide", "Canberra"], correctAnswer: 3) ] var currentQuestion: Question? var currentQuestionPos = 0 var noCorrect = 0
First of all we are setting up a structure to hold each question. It will store the question, the four possible answers and the index of the correct answer.
Then we populate the questions variable with three questions. Remember an array starts at 0, so a correctAnswer of 0 is the first item.
Finally we store the currentQuestion in a variable, and the currentQuestionPos which is the position of the current question. Then we store the number we have correct as noCorrect which starts at 0.
Next up add the code as follows – for the submitAnswer0-4 you will already have these functions, so simply add the code for them. The functions are commented as to what they do and how they work.
// Submit an answer @IBAction func submitAnswer0(_ sender: Any) { checkAnswer(idx: 0) } @IBAction func submitAnswer1(_ sender: Any) { checkAnswer(idx: 1) } @IBAction func submitAnswer2(_ sender: Any) { checkAnswer(idx: 2) } @IBAction func submitAnswer3(_ sender: Any) { checkAnswer(idx: 3) } // Check if an answer is correct then load the next question func checkAnswer(idx: Int) { if(idx == currentQuestion!.correctAnswer) { noCorrect += 1 } loadNextQuestion() } func loadNextQuestion() { // Show next question if(currentQuestionPos + 1 < questions.count) { currentQuestionPos += 1 currentQuestion = questions[currentQuestionPos] setQuestion() // If there are no more questions show the results } else { performSegue(withIdentifier: "sgShowResults", sender: nil) } } // Set labels and buttions for the current question func setQuestion() { lblQuestion.text = currentQuestion!.question answer0.setTitle(currentQuestion!.answers[0], for: .normal) answer1.setTitle(currentQuestion!.answers[1], for: .normal) answer2.setTitle(currentQuestion!.answers[2], for: .normal) answer3.setTitle(currentQuestion!.answers[3], for: .normal) lblProgress.text = "\(currentQuestionPos + 1) / \(questions.count)" } // Set the background as a blue gradient func setGradientBackground() { let colorTop = UIColor.black.cgColor let colorBottom = UIColor.blue.cgColor let gradientLayer = CAGradientLayer() gradientLayer.colors = [ colorTop, colorBottom] gradientLayer.locations = [ 0.0, 1.0] gradientLayer.frame = self.view.bounds self.view.layer.insertSublayer(gradientLayer, at: 0) } // Before we move to the results screen pass the how many we got correct, and the total number of questions override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if(segue.identifier == "sgShowResults") { var vc = segue.destination as! ResultsViewController vc.noCorrect = noCorrect vc.total = questions.count } }
Now to setup the first question when the app loads add the code to viewDidLoad(). It will load the first question, set the labels and buttons to reflect this question and setup the gradient background.
override func viewDidLoad() { super.viewDidLoad() currentQuestion = questions[0] setQuestion() setGradientBackground() }
Coding the Results Screen
Now we are finished off with the quiz side of the app, its time to code the results screen. This is alot quicker then the code we have done so far. Go to the ResultsViewController, above viewDidLoad add the following class level varibles to store the amount the user got correct, and the total number of questions.
var noCorrect = 0 var total = 0
Then in viewDidLoad add your code as follows, the comments explain how it shows the results
override func viewDidLoad() { super.viewDidLoad() // Set the results lblResults.text = "You got \(noCorrect) out of \(total) correct" // Calculate the percentage of quesitons you got right var percentRight = Double(noCorrect) / Double(total) percentRight *= 100 // Based on the percentage of questions you got right present the user with different message var title = "" if(percentRight < 40) { title = "Not Good" } else if(percentRight < 70) { title = "Almost" } else { title = "Good Job" } lblTitle.text = title }
Nice work – this finishes of our coding for our quiz up. You can run the code and see it in action! Play around with the questions to add and remove your own. You can also change the design, or even set up an app that has multiple quiz’s inside it.