Jei
Jei

Reputation: 49

Using UserDefaults to store score for a clicker game (Swift 5)

Have made a simple incremental game. I want it so that even if I go to a different VC and then return to the game, or reopen the game, it will show the current score. My issue is that if I leave the game, then the score will return back to zero. I do not want that to happen. The score should not be resetting. I've heard I could use UserDefaults but I am not familiar to it at all. If you can explain using code, that would be best. Thanks.

import UIKit

class CookieClickerVC: UIViewController {

@IBOutlet weak var goldLabel: UILabel!
@IBOutlet weak var numberOfGold: UILabel!
@IBOutlet weak var getGoldButton: UIButton!

override func viewDidLoad() {
    super.viewDidLoad()
    formatItems()
    let defaults = UserDefaults.standard
    defaults.set(0, forKey: "goldCount")

}



@IBAction func getGoldClicked(_ sender: Any) {
    goldCount += 1
    numberOfGold.text = ("\(goldCount)")
}`

also, you may have already figured out, but goldCount is an unresolved identifier. How should I change the code after button is clicked?

Upvotes: 1

Views: 264

Answers (5)

Jawad Ali
Jawad Ali

Reputation: 14397

You can use these funtions to get and set score

class CookieClickerVC: UIViewController {

    @IBOutlet weak var goldLabel: UILabel!
    @IBOutlet weak var numberOfGold: UILabel!
    @IBOutlet weak var getGoldButton: UIButton!


   lazy var goldCount : Int = 0 {
         didSet {
        numberOfGold.text = ("\(goldCount)")
       }
   }

   override func viewDidLoad() {
        super.viewDidLoad()
        formatItems()
        goldCount = getScore()

    }

    @IBAction func getGoldClicked(_ sender: Any) {
        goldCount += 1
        savescore(goldCount)
    }

    //  Save and Get methods ..

    func saveScore(_ score:Int) {
            let defaults = UserDefaults.standard
            defaults.set(score, forKey: "goldCount")
          //  defaults.synchronize() its [unnecessary][1] 
        }

// defaults.synchronize() its unnecessary

    func getScore()-> Int {
          let defaults = UserDefaults.standard
          return  defaults.integer(forKey: "goldCount")
        }
}

Upvotes: 5

Rob
Rob

Reputation: 2164

import UIKit

class CookieClickerVC: UIViewController {

@IBOutlet weak var goldLabel: UILabel!
@IBOutlet weak var numberOfGold: UILabel!
@IBOutlet weak var getGoldButton: UIButton!

private var goldCount: Int = Int()

override func viewDidLoad() {
    super.viewDidLoad()
    formatItems()

}



@IBAction func getGoldClicked(_ sender: Any) {
    goldCount += 1

    numberOfGold.text = ("\(goldCount)")

    UserDefaults.standard.set(goldCount, forKey: "goldCount")

    UserDefaults.standard.synchronize()

   //To get the count again you can use

     print(UserDefaults.standard.integer(forKey: "goldCount")
}

Whenever there is an increment you can save the value of goldCount like this in your UserDefault and I have also added how can you fetch the same value from UserDefault.

Upvotes: 2

Mango
Mango

Reputation: 187

You can change your viewDidLoad function to check the UserDefaults for the "goldCount" key first, and if it has a value, use it. If not just set the score to 0.

override func viewDidLoad() {
    super.viewDidLoad()
    formatItems()
    let defaults = UserDefaults.standard

    if let savedScore = defaults.value(forKey: "goldCount") as? Int {
        goldCount = savedScore
    } else {
        defaults.set(0, forKey: "goldCount")
    }
}

You can define "goldCount" as var goldCount: Int = 0 below your IBOutlets.

Also as a further optimization, you can extract the "goldCount" string to use as let goldCountKey: String = "goldCount" and use it like defaults.set(0, forKey: goldCountKey). Avoiding hard-coded strings is a good practice in my opinion, but not that crucial in this case.

To save the new value in every click, add UserDefaults.standard.set(goldCount, forKey: goldCountKey) in getGoldClicked. Another idea here would be to add this in your AppDelegate's willTerminate function to make sure you get your value saved when the application is terminated. Though that will require references to goldCount value there, so no rush.

Hope it helps!

Upvotes: 2

chirag90
chirag90

Reputation: 2240

Try the below

class ViewController: UIViewController {

    @IBOutlet weak var numberOfGold: UILabel!
    @IBOutlet weak var highScore: UILabel!

    //declare your count variable globally
    var goldCount : Int = 0
    let defaults = UserDefaults.standard

    override func viewDidLoad() {
        super.viewDidLoad()
        //get the highscore and then set it to label
        let userHighScore = getUserScore()
        highScore.text = "\(userHighScore)"

    }

    @IBAction func goldButtonClicked(_ sender: Any) {
        goldCount += 1
        numberOfGold.text = "\(goldCount)"
    }

    //function to say game finished and store the score in userdefault
    //call this function when the gameHasFinished
    func gameFinished() {
        saveUserScore(goldCount)
    }

    func saveUserScore(_ score:Int){
        defaults.set(score, forKey: "goldCount")
    }
    func getUserScore()-> Int {
        return  defaults.integer(forKey: "goldCount")
    }
}

Upvotes: 2

Keshu R.
Keshu R.

Reputation: 5225

Step 1: declare your goldCount variable and set the initial value to 0

Step 2: on viewDidLoad, get the value stored in the UserDefaults and set it to goldCount

Step 3: Also update your label

Step 4: Update the value of goldCount in userDefaults

import UIKit

class CookieClickerVC: UIViewController {

    @IBOutlet weak var goldLabel: UILabel!
    @IBOutlet weak var numberOfGold: UILabel!
    @IBOutlet weak var getGoldButton: UIButton!

    //Step1: declare your goldCount variable and set initial value to 0
    var goldCount = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        formatItems()
        //Step2: on viewDidLoad, get the value stored in the UserDefaults and set it to goldCount
        goldCount = UserDefaults.standard.integer(forKey: "goldCount")
        //Step3: then also update your label
        numberOfGold.text = ("\(goldCount)")


    }

    @IBAction func getGoldClicked(_ sender: Any) {
        goldCount += 1
        numberOfGold.text = ("\(goldCount)")
        //Step4: update the value of goldCount in userDefaults
        UserDefaults.standard.set(goldCount, forKey: "goldCount")
    }
}

Upvotes: 6

Related Questions