Hacking with Swift – Challenge 2

Day 21

For the 21st day of the 100 Days of Swift initiative it is time to recap what was learned during the second project, the first game in the series and to face the second challenge.

Here is what we learned in this project:

  • The size inspector lets us specify precise sizes and positions for our app’s views.
  • We can add borders to buttons and other views.
  • Asset catalogs store many images at different sizes to allow for different devices’ management.
  • CALayer is part of Core Animation, a lower level technical part compared to UIKit.
  • Multiple buttons can call the same method when tapped (this is done by connecting the same IBAction).
  • Auto Layout constraints can position one view relative to another.
  • We can use values higher than 1.0 for red, green, and blue in UIColor.
  • Tags let us identify views uniquely.
  • All Swift’s numeric types have a random(in:) method. This is a new thing as of iOS 12, a very VERY welcomed addition!
  • Alpha represents how transparent a view is.
  • You can add many items to an array by using +=
  • @2x and @3x images make sure our images look great on all screen resolutions.

Among many other things, refer to my other article for the full report of the learning process.

Today’s challenges

  1. We need to show the player’s score in the navigation bar, alongside the flag to guess.
  2. Keep track of how many questions have been asked, and show one final alert controller after they have answered 10. This should show their final score.
  3. When someone chooses the wrong flag, tell them their mistake in your alert message – something like “Wrong! That’s the flag of France,” for example.

Well, today’s challenges are significantly stronger than the first round’s ones and they will require quite a lot more of thinking. Let’s start from the beginning.

Show the player’s score in the navigation bar

The text shown in the navigation bar is found in the askQuestion(action:) method. Just before the last line of code I created a constant to hold the code held before by the title property, as I would like the string interpolation to look nicer.

let uppercasedCountry = countries[correctAnswer].uppercased()

title = "Score: \(score) — Tap on: \(uppercasedCountry)'s flag.

This works! Sure, I could have used shorter property names but this is a smaller thing for me now.

The score updates but my gut says that I could somehow make it update behind the alert window, not after I click the Continue button. I guess I could change the handler in the call to addAction but I feel like not breaking things now. After all, when you score a goal, the referee validates it and then the screen gets updated with the new score, right?

Show final alert after 10 questions

Good, now let’s take a deep breath and let’s try to do things in order.

Keep track of how many questions have been asked

I feel this should be a global property in ViewController.swift

var askedQuestions = 0

Show one final alert controller.

My approach, for sure not the only possible one, has been to manage which alert controller will be shown with a control flow statement. That is: if askedQuestions < 10 we will show the regular alert controller, else we will show another one. Here is the code, with a small bonus.

if askedQuestions < 10 {
    let alertController = UIAlertController(title: title, message: "Your score is \(score).", preferredStyle: .alert)
    alertController.addAction(UIAlertAction(title: "Continue", style: .default, handler: askQuestion))
    present(alertController, animated: true)
} else {
    let finalAlertController = UIAlertController(title: "Game over!", message: "Your score is \(score).", preferredStyle: .alert)
    finalAlertController.addAction(UIAlertAction(title: "Start new game!", style: .default, handler: startNewGame))
    present(finalAlertController, animated: true)

Start a new game!

I allowed myself a little derailment from the challenge as I would like my game to start again after the end. I could have written nil inside of the finalAlertController‘s handler but I decided to create a new method like this:

// Start a new game
    func startNewGame(action: UIAlertAction) {
        score = 0
        askedQuestions = 0

Calling this will show up an Alert after question 10 has been asked and upon pressing “Start New Game” we will be brought back to the beginning!

Screen Shot 2019-02-21 at 20.04.28

Correct user’s mistakes!

This is much simpler than the previous task: simply change the title string in the else statement of the buttonTapped action to this:

title = "Wrong! That's the flag of \(countries[sender.tag].uppercased())"

Screen Shot 2019-02-21 at 20.03.12

That’s all for this project’s challenges.

Please let me know in the comments how you solved these and what would you change in my code. I am pretty sure there are plenty of more elegant ways of solving these challenges but I am writing this to keep track of my progress and of my learning path.

Here is the source code for the finished challenges.

Thank you for following me until here!

If you like what I’m doing here please consider liking this article and sharing it with some of your peers. If you are feeling like being really awesome, please consider making a small donation to support my studies and my writing (please appreciate that I am not using advertisement on my articles).

If you are interested in my music engraving and my publications don’t forget visit my Facebook page and the pages where I publish my scores (Gumroad, SheetMusicPlus, ScoreExchange and on Apple Books).

You can also support me by buying Paul Hudson’s books from this Affiliate Link.

Anyways, thank you so much for reading!

Till the next one!

Published by Michele Galvagno

Professional Musical Scores Designer and Engraver Graduated Classical Musician (cello) and Teacher Tech Enthusiast and Apprentice iOS / macOS Developer Grafico di Partiture Musicali Professionista Musicista classico diplomato (violoncello) ed insegnante Appassionato di tecnologia ed apprendista Sviluppatore iOS / macOS

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: