-4
class ThirdViewController: UIViewController {

var i = 3

var a: Double = 0

var fastestScore:Float = 100000000000000.0

var randomNumberX = Int(arc4random_uniform(375))

var randomNumberY = Int(arc4random_uniform(667))


@IBOutlet weak var fastestScoreLabel: UILabel!

@IBOutlet weak var homeButtonLabel: UIButton!

@IBOutlet weak var finalLabel: UILabel!

@IBOutlet weak var playAgainButtonLabel: UIButton!

@IBOutlet weak var circleImage: UIButton!

@IBOutlet weak var secondTimerLabel: UILabel!

@IBOutlet weak var counterLabel: UILabel!

var timerA = Timer()

var timerB = Timer()

@IBAction func homeButton(_ sender: Any) {

    nextPage = false

}

@IBAction func playAgainButton(_ sender: Any) {

    randomNumberX = Int(arc4random_uniform(375))

    randomNumberY = Int(arc4random_uniform(667))

    homeButtonLabel.isHidden = true

    counterLabel.text = "3"

    i = 3

    timerA = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ThirdViewController.counterFunc), userInfo: nil, repeats: true)

    a = 0

    counterLabel.isHidden = false

    playAgainButtonLabel.isHidden = true

    circleImage.isHidden = true

    finalLabel.isHidden = true

    secondTimerLabel.isHidden = true

    fastestScoreLabel.isHidden = true

}

@IBAction func circleButton(_ sender: Any) {

    fastestScoreLabel.isHidden = false

    circleImage.isHidden = true

    homeButtonLabel.isHidden = false

    timerB.invalidate()

    playAgainButtonLabel.isHidden = false

    var saying = ""

    if a < 0.2 {

        saying = "That's actually pretty good \(a) seconds is pretty fast"

    } else if a >= 0.2 && a <= 0.45 {

        saying = "\(a) seconds is not really that good"

    } else {

        saying = "\(a) seconds? Seriously? Are you even trying?"

    }

    finalLabel.text = saying

    finalLabel.isHidden = false

    if Float(a) < fastestScore {

        fastestScore = Float(a)

        UserDefaults.standard.set(fastestScore, forKey: "Fastest Score")

        let savedFastestScore = UserDefaults.standard.float(forKey: "Fastest Score")

        fastestScoreLabel.text = String(savedFastestScore)

    }


}

func secondTimer() {

    a = a + 0.01

    secondTimerLabel.text = String(a)

}

func counterFunc() {

    if i > 1 {

        i -= 1

        counterLabel.text = String(i)

    } else {

        timerB = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(ThirdViewController.secondTimer), userInfo: nil, repeats: true)

        circleImage.isHidden = false

        self.circleImage.center = CGPoint(x:randomNumberX, y:randomNumberY)

        counterLabel.isHidden = true

        timerA.invalidate()

        secondTimerLabel.isHidden = false

    }

}

override func viewDidLoad() {
    super.viewDidLoad()


    fastestScoreLabel.isHidden = true

    homeButtonLabel.isHidden = true

    playAgainButtonLabel.isHidden = true

    circleImage.isHidden = true

    secondTimerLabel.isHidden = true

    timerA = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ThirdViewController.counterFunc), userInfo: nil, repeats: true)

    // Do any additional setup after loading the view.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.
}
*/

}

I have tried many different times using userDefaults to try and save the highscore when you close out but I just can't seem to do it. If someone has any idea on how to do it I would really appreciate it lol.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
Reid Brown
  • 13
  • 4
  • 4
    Welcome to stackoverflow! Your question is about `UserDefaults`, and you posted some code (good!), but the code you posted doesn't try to use `UserDefaults` (bad...). You need to show us what code you've written that actually tries to use `UserDefaults`, and what you think is wrong with it (e.g. the exact error you get from the compiler, or a description of the run-time behavior and how it's incorrect). – rob mayoff May 16 '17 at 20:47
  • Ok, One second I will run it with what I had sorry I just took it out so it was easier to read. – Reid Brown May 16 '17 at 20:50
  • @rob I uploaded the edited code now and I have had some other comments saying that I need to do synchronize() – Reid Brown May 16 '17 at 21:10
  • 1
    You do not need to call `synchronize`. [This article by the Apple engineer responsible for `NSUserDefaults`](http://dscoder.com/defaults.html) says “It is almost never necessary to call `-synchronize` after setting a preference \[…\] and users are generally not capable of changing settings fast enough for any sort of "batching" to be useful for performance.” – rob mayoff May 16 '17 at 21:19
  • @rob I have tried updating this and it still won't work. Have any suggestions? – Reid Brown May 16 '17 at 21:56

2 Answers2

0

When you are saving high scores, make sure that the current score you have is greater than the new score.

suppose the current high score is 100

 var fastestScore = 100 
 var currentScore: Int?


if currentScore < fastestScore { 
          Userdefaults.standard.set(currentScore, forKey: "Fastest Score") 


}

The code above will go to the function where you need to save the high score. Maybe in your game over scene.

To retrieve the low score, do this

var savedFastestScore = UserDefaults.standard.float(forKey: "Fastest Score")
Cyril
  • 2,783
  • 1
  • 24
  • 35
  • 1
    You do not need to call `synchronize()`. – rmaddy May 16 '17 at 21:05
  • @rmaddy I've seen many examples that tell me to use synchronize(). What does it actually do and why do I not need it? – Cyril May 16 '17 at 21:06
  • see http://stackoverflow.com/questions/40808072/when-and-why-should-you-use-nsuserdefaultss-synchronize-method – rmaddy May 16 '17 at 21:07
  • @Cyril It is kind of confusing but the highscore in itself is the smallest time that it took to click on the button, so it really is the low score. So when the "current score" is lower than the highscore it needs to change and save and I can't manage to make this happen – Reid Brown May 16 '17 at 21:08
  • @ReidBrown From my understanding, you want to save the lowest score. So in that case, I would just change the greater than sign to less than sign. – Cyril May 16 '17 at 21:10
  • ok @cyril and would I need to put anything under ViewDidLoad or is this all I need – Reid Brown May 16 '17 at 21:13
  • @ReidBrown No, in your case, you would use this code wherever the user clicks a button – Cyril May 16 '17 at 21:14
  • @cyril I have been trying for like 45 minutes to incorporate this into the code I will update it above I dont know what the problem is – Reid Brown May 16 '17 at 21:53
  • @ReidBrown Can you describe what is not working? What is happening when you hit the button? – Cyril May 16 '17 at 21:57
  • @cyril the highscore is working while I am using it but when I reload the app it doesnt save – Reid Brown May 16 '17 at 22:00
  • @ReidBrown In your fastestScore declaration, change that to a float data type. `var fastestScore: Float = 100000000.0` – Cyril May 16 '17 at 22:02
  • @cyril I did that and it still won't work do you have any other suggestions? – Reid Brown May 16 '17 at 22:07
  • @ReidBrown That was actually a bad suggestion. Move ` let savedFastestScore = UserDefaults.standard.float(forKey: "Fastest Score") ` to your `viewDidLoad` and use set your `highScoreLabel` to `savedFastestScore` If that doesnt work. upload your project and I'll take a look. – Cyril May 16 '17 at 22:10
0

You still haven't clearly explained what problem you're seeing, but my guess is that your high score doesn't appear to be saved across restarts of the app.

The problem is that you initialize fastestScore to 100000000000000.0 when your ThirdViewController is created. You don't load it from UserDefaults. Thus even if there is a stored fastestScore, you don't load it at launch.

You should fix this with two changes. First, in your application delegate, you should register a default high score:

let bestScoreKey = "bestScore"

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, willFinishLaunchingWithOptions options: [UIApplicationLaunchOptionsKey : Any]?) -> Bool {
        UserDefaults.standard.register(defaults: [
            bestScoreKey: 1_000_000_000.0
        ])
        return true
    }

}

You should also register any other default settings there.

Second, in ThirdViewController, you should initialize fastestScore from UserDefaults. You can also save changes back to UserDefaults in the property's didSet observer:

    var fastestScore: Double = UserDefaults.standard.double(forKey: bestScoreKey) {
        didSet {
            UserDefaults.standard.set(fastestScore, forKey: bestScoreKey)
        }
    }

Other tips:

  • There is no reason to make fastestScore a Float if your scores are Double. Just save it as a Double.

  • Don't repeat string keys. The compiler won't catch your spelling errors. Put the key in a constant like I did with bestScoreKey.

  • You can use _ in long numbers to make them more readable.

  • Insulting your player is a questionable marketing strategy. How would you have felt if the first comment on your question was “Seriously? Are you even trying?”

rob mayoff
  • 375,296
  • 67
  • 796
  • 848