Search code examples
iosswiftnsuserdefaults

High score Label not updating - UserDefaults and Swift 4


The resource that I got this code from was written in Swift 3 and works appropriately. My app is written in Swift 4. I think that I may be missing something that is specific to Swift 4 but I can't figure out what it may be.

I have the appropriate outlets and variable ...

@IBOutlet weak var scoreLabel: UILabel!
@IBOutlet weak var highScoreLabel1: UILabel!

var recordData: String!

viewDidLoad and viewDidAppear are accounted for ...

override func viewDidLoad() {
    super.viewDidLoad()

    let userDefaults = Foundation.UserDefaults.standard
    let value = userDefaults.string(forKey: "Record")
    recordData = value

}

override func viewWillAppear(_ animated: Bool) {
    let userDefaults = Foundation.UserDefaults.standard
    let value = userDefaults.string(forKey: "Record")

    if (value == nil) {
        highScoreLabel1.text = "0"

    } else {

        highScoreLabel1.text = value
    }
}

I created a function that I though would work ...

func high score () {

    if gameMode == 0 {

        if recordData == nil {

            let savedString = scoreLabel.text
            let userDefaults = Foundation.UserDefaults.standard
            userDefaults.set(savedString, forKey: "Record")

        } else {

            let score: Int? = Int(scoreLabel.text!)
            let record: Int? = Int(recordData)

            if score! > record! {

                let savedString = scoreLabel.text
                let userDefaults = Foundation.UserDefaults.standard
                userDefaults.set(savedString, forKey: "Record")

            }
        }
    }
}

Solution

  • The high score label is not updating because there is no code. The label is only set (once) in viewDidLoad / viewWillAppear.

    I highly recommend to save the high score as Int. That avoids the optionals and the code can be reduced dramatically.

    • Declare recordData

      var recordData = 0
      
    • Delete the code in viewDidLoad. Loading the data once in viewWillAppear is sufficient.

    • Replace viewWillAppear with

      override func viewWillAppear(_ animated: Bool) {
          super.viewWillAppear(animated)
          // integer(forKey returns 0 if the key is not used yet
          highScoreLabel1.text = String(UserDefaults.standard.integer(forKey: "Record"))
      }
      
    • Replace highscore with

      func highscore() {
          guard gameMode == 0, let score = Int(scoreLabel.text!), score > recordData else { return }
          recordData = score
          UserDefaults.standard.set(recordData, forKey: "Record")
          highScoreLabel1.text = String(recordData)
      }