Home iOS & Swift Books iOS Apprentice

18
Polish Written by Eli Ganim

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

You can unlock the rest of this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

At this point, your game is fully playable. The gameplay rules are all implemented and the logic doesn’t seem to have any big flaws, but there’s still some room for improvement.

This chapter will cover the following:

  • Tweaks: Small UI tweaks to make the game look and function better.
  • The alert: Updating the alert view functionality so that the screen updates after the alert goes away.
  • Start over: Resetting the game to start afresh.

Tweaks

Obviously, the game is not very pretty yet — you will get to work on that soon. In the mean time, there are a few smaller tweaks you can make.

The alert title

Unless you already changed it, the title of the alert still says “Hello, World!” You could give it the name of the game, Bullseye, but there’s a better idea. What if you change the title depending on how well the player did?

@IBAction func showAlert() {
  let difference = abs(targetValue - currentValue)
  let points = 100 - difference
  score += points

  // add these lines
  let title: String
  if difference == 0 {
    title = "Perfect!"
  } else if difference < 5 {
    title = "You almost had it!"
  } else if difference < 10 {
    title = "Pretty good!"
  } else {
    title = "Not even close..."
  }

  let message = "You scored \(points) points"

  let alert = UIAlertController(title: title,  // change this
                              message: message, 
                       preferredStyle: .alert)

  let action = UIAlertAction(title: "OK", style: .default, 
                           handler: nil)
  alert.addAction(action)
  present(alert, animated: true, completion: nil)

  startNewRound()
}

Constant initialization

In the above code, did you notice that title was declared explicitly as being a String constant? And did you ask yourself why type inference wasn’t used there instead? Also, if title is a constant, how do we have code which sets its value in multiple places?

let title = ""
var title = ""
A constant needs to be initialized exhaustively
E yuvxwehk beews ti ho eyegoafoyab ofpuahzewukk

The alert with the new title
Yxa ogekn tocs mco wik xohvu

Bonus points

Exercise: Give players an additional 100 bonus points when they get a perfect score. This will encourage players to really try to place the bullseye right on the target. Otherwise, there isn’t much difference between 100 points for a perfect score and 98 or 95 points if you’re close but not quite there.

@IBAction func showAlert() {
  let difference = abs(targetValue - currentValue)
  var points = 100 - difference     // change let to var

  let title: String
  if difference == 0 {
    title = "Perfect!"
    points += 100                   // add this line
  } else if difference < 5 {
    title = "You almost had it!"
    if difference == 1 {            // add these lines
      points += 50					// add these lines
    }								// add these lines
  } else if difference < 10 {
    title = "Pretty good!"
  } else {
    title = "Not even close..."
  }
  score += points                   // move this line here from the top
  . . .
}
Raking in the points…
Bugaww ix tsu piepvy…

The alert

One annoying thing about the app is that as soon as you tap the Hit Me! button and the alert pops up, the slider immediately jumps back to its center position, the round number increments, and the target label already gets the new random number.

Asynchronous code execution

Maybe you’re wondering why this isn’t already happening? After all, in showAlert() you only call startNewRound() after you’ve shown the alert pop-up:

@IBAction func showAlert() {
  . . .
  let alert = UIAlertController(. . .)
  let action = UIAlertAction(. . .)
  alert.addAction(action)

  // Here you make the alert visible:
  present(alert, animated: true, completion: nil)

  // Here you start the new round:
  startNewRound()
}

Alert event handling

So, if your code execution can’t wait in showAlert() until the pop-up is dismissed, then how do you wait for it to close?

let action = UIAlertAction(title: "OK", style: .default, handler: nil)
@IBAction func showAlert() {
  . . .
  let alert = UIAlertController(. . .)

  let action = UIAlertAction(title: "OK", style: .default, 
                           handler: { _ in
                                         self.startNewRound()
                                    })

  alert.addAction(action)
  present(alert, animated: true, completion: nil)
}

Start over

No, you’re not going to throw away the source code and start this project all over! This part is about the game’s “Start Over” button. This button is supposed to reset the score and start over from the first round.

The new method

First, add a method to ViewController.swift that starts a new game. You should put it near startNewRound() because the two are conceptually related.

func startNewGame() {
  score = 0
  round = 0
  startNewRound()
}
@IBAction func startOver() {
  startNewGame()
}
@IBAction func startNewGame() {
  score = 0
  round = 0
  startNewRound()
}
override func viewDidLoad() {
  super.viewDidLoad()
  startNewGame()        // this line changed
}

Connect the outlet

Finally, you need to connect the Start Over button to the action method.

All the connections from View Controller to the other objects
Enk wqi nihrazvaokr rteb Poip Hacrxoqwoz ce sfe ampeg emroxmv

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.

Have feedback to share about the online reading experience? If you have feedback about the UI, UX, highlighting, or other features of our online readers, you can send them to the design team with the form below:

© 2021 Razeware LLC

You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

Unlock Now

To highlight or take notes, you’ll need to own this book in a subscription or purchased by itself.