var score = 0
var highscore = 0
var defaults = NSUserDefaults.standardUserDefaults()
#IBOutlet weak var scoreResult: UILabel!
#IBOutlet weak var highScoreResult: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
if let hscore = defaults.valueForKey("highscore") {
highScoreResult.text = String(hscore)
}
}
#IBAction func tapPressed(sender: AnyObject) {
score++
scoreResult.text = String(score)
if score > highscore {
highscore = score
highScoreResult.text = String(highscore)
defaults.setValue(highscore, forKey: "highscore")
defaults.synchronize()
}
}
When i press "tapPressed" button, score++ , then it saves as highscore, the problem is that when i restart app and i have highscore saved. When i press "tapPressed" highscore starts from zero again.
Change viewDidLoad to:
override func viewDidLoad() {
super.viewDidLoad()
if let hscore = defaults.valueForKey("highscore") {
highscore = hscore
highScoreResult.text = String(hscore)
}
}
That should load the highscore from the defaults once you're app launches.
In your viewDidLoad you need to change your statement to this:
if let hscore = defaults.valueForKey("highscore") {
highscore = hscore
highScoreResult.text = String(hscore)
}
The other answers are describing the reason for the error. In addition I'd like to describe also to use NSUserDefaults properly.
The recommended way is to register the key/value pairs to have reliable default values in case the preference file will be deleted or the app launches the first time.
In AppDelegate (applicationDidFinishLaunching or earlier) register highscore with a value of 0.
let defaultValues = ["highscore" : 0]
defaults.registerDefaults(defaultValues)
Then in viewDidLoad just write
let highscore = defaults.integerForKey("highscore")
highScoreResult.text = String(highscore)
There is no optional binding needed because the value in user defaults is always a non optional.
To save highscore back to disk use the dedicated method setInteger:forKey:
defaults.setInteger(highscore, forKey: "highscore")
valueForKey: is a KVC method with a special meaning and should not be used with NSUserDefaults.
Related
I am working on saving data process,
because my data is small, so I want to save in local data storage.
I want a make time schedule.
Because I have single 35 buttons and label(each buttons and label are paired), So I am using UIButton tag now. And I have a problem on using other local data "tag".
I tired to make new func on global swift file(same swift file). but it is not able to call tag, because tag is only can use when UIbutton pressed.
I want to use tag property on viewDidLoad(), not only in UIbuttonPressed.
override func viewDidLoad() {
if let items = UserDefaults.standard.array(forKey: "SubjectList") as? [String] {
subjectArray = items
UITextLabel**1**.text = subjectArray**[1-1]**
}
}
#IBAction func buttonPressed(_ sender: UIButton) {
var textField = UITextField()
let newItem = textField.text!
if sender.tag == 1{
self.subjectArray[sender.tag-1] = newItem
print("1")
}
UserDefaults.standard.set(self.subjectArray, forKey: "SubjectList")
}
Create outlet collections for all the paired labels and buttons
#IBOutlet weak var allLbls:[UILabel]!
#IBOutlet weak var allBts:[UIButton]!
In viewDidLoad
if let items = UserDefaults.standard.array(forKey: "SubjectList") as? [String] {
subjectArray = items
subjectArray.indices?.forEach {
allLbls[$0].text = subjectArray[$0]
allBts[$0].tag = $0
}
}
I'm storing an integer using User Defaults, but the number I'm trying to store was transferred via segue (ageFromSettings) and needs to have a default value.
The problem is that the data that was transferred via segue gets stored when presented, but when the app restarts it stores the default value.
Any ideas how to save an item that was passed via segue?
class ViewController: UIViewController {
#IBOutlet weak var youHaveLabel: UILabel!
#IBOutlet weak var daysLeftLabel: UILabel!
#IBOutlet weak var leftToLiveLabel: UILabel!
#IBAction func settingsButtonPressed(_ sender: Any) {
performSegue(withIdentifier: "toSettings", sender: nil)
}
var daysLeft = 0
var ageFromSettings = 36500
override func viewDidAppear(_ animated: Bool) {
UserDefaults.standard.set(ageFromSettings, forKey: "persistedAge")
if let age = UserDefaults.standard.object(forKey: "persistedAge") as? Int{
print("age: \(age)")
daysLeft = age
}
if daysLeft == 36500 {
daysLeftLabel.alpha = 0
youHaveLabel.alpha = 0
leftToLiveLabel.text = "Set your age in Settings"
} else if daysLeft == -1{
leftToLiveLabel.text = "Day On Borrowed Time"
} else if daysLeft == 0{
leftToLiveLabel.text = "Statistically, you died today"
} else if daysLeft == 1{
leftToLiveLabel.text = "Day Left to Live"
} else if daysLeft < 0 {
leftToLiveLabel.text = "Days on Borrowed Time"
}
if daysLeft > -1 {
daysLeftLabel.text = String(daysLeft)
} else {
daysLeftLabel.text = String(daysLeft * -1)
}
}
}
The problem is that you are saying:
UserDefaults.standard.set(ageFromSettings, forKey: "persistedAge")
if let age = UserDefaults.standard.object(forKey: "persistedAge") as? Int{
That's nutty. In the second line, we know that UserDefaults contains a persistedAge key, and we know what its value is — because you just put it there, in the first line. And you're doing that even if you have already set a different persistedAge value on a previous run of the app.
Delete the first line. If your goal is to supply an initial default value, use register(defaults:_). That's what it's for. It will be used only just in case you have not called set(_:forKey:) yet.
In your case, you are setting the value of the persistedAge key every single time in the viewDidAppear(_:) method of your view controller. Right afterwards, you are retrieving the data and trying to read it, which is somewhat redundant. In the latter case, you will also be resetting the value of the persistedAge key every time your view controller appears.
I am working on an app that involves the use of NSUserDefaults. I have successfully saved two strings and am currently trying to save an int.
This is the code
var number = Int(0)
override func viewDidLoad() {
super.viewDidLoad()
let numberOne = NSUserDefaults.standardUserDefaults()
numberOne.setValue(number, forKey: "num")
let numberTwo = numberOne.stringForKey("num")
if numberTwo > 1
{
//will insert code later
}
my error is that numberTwo is appearing as a string. This is my first time experimenting with NSUserDefault so, I am a novice but, any help is appreciated.
In case of you want to treat it as an integer value, you should set (saving) and get the value as an integer, by using setInteger:forKey: and integerForKey::
var number = Int(0)
override func viewDidLoad() {
super.viewDidLoad()
let numberOne = NSUserDefaults.standardUserDefaults()
numberOne.setInteger(number, forKey: "num")
let numberTwo = numberOne.integerForKey("num") // 0
if numberTwo > 1
{
//will insert code later
}
}
If your value is an Int you can retrieve it with (Swift 3)
let numberTwo = numberOne.integer(forKey: "num")
If Swift 2 I believe it was
let numberTwo = numberOne.integerForKey("num")
You can take a look at the UserDefaults API Reference for more details and more options (such as object(forKey:), string(forKey:)...)
So in the app I'm creating I have a settings view controller where users can type their information in the textfields and then when they click the done button it loads all that information to labels on the home view controller . How can I save the data in the home view controller with NSUserDefault? I'm using two view controllers.
Settings View Controller
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?){
let DestViewController = segue.destinationViewController as! home
DestViewController.NameText = NameTextField.text!
DestViewController.positionText = positionTextField.text!
DestViewController.divisionText = divisionTextField.text!
DestViewController.routeText = routeTextField.text!
DestViewController.routeText = routeTextField.text!
DestViewController._picture = _picture.image!
NSUserDefaults.standardUserDefaults().setValue(NameTextField.text!, forKey: "name")
NSUserDefaults.standardUserDefaults().setValue(positionTextField.text!, forKey: "position")
NSUserDefaults.standardUserDefaults().setValue(divisionTextField.text!, forKey: "division")
NSUserDefaults.standardUserDefaults().setValue(routeTextField.text!, forKey: "route")
NSUserDefaults.standardUserDefaults().setValue(_picture, forKey: "ImageKey")
}
Home View Controller
class home: UIViewController, UITextFieldDelegate {
#IBOutlet weak var Name: UILabel!
#IBOutlet weak var position: UILabel!
#IBOutlet weak var division: UILabel!
#IBOutlet weak var route: UILabel!
var contacts = MyContacts()
var NameText = String()
var positionText = String()
var divisionText = String()
var routeText = String()
var _picture: UIImage!
override func viewDidLoad() {
super.viewDidLoad()
Name!.text = NSUserDefaults.standardUserDefaults().stringForKey("name")
position!.text = NSUserDefaults.standardUserDefaults().stringForKey("position")
division!.text = NSUserDefaults.standardUserDefaults().stringForKey("division")
route!.text = NSUserDefaults.standardUserDefaults().stringForKey("route")
Profile!.image = _picture
}
All of these codes work perfect, I'm just wondering if you could help me save the labels in NSUserDefault so every time the app is loaded all the information is still there. I've done a lot of research on this topic, but can find a solution for my problem. Any help would be much appreciated.
Just use basic syntax:
NSUserDefaults.standardUserDefaults().setValue(value, forKey:key)
Save example:-
NSUserDefaults.standardUserDefaults().setValue(positionTextField.text!, forKey: "position")
Retrieve example:-
position!.text=NSUserDefaults.standardUserDefaults().stringForKey("position")
Note: remember the key must be unique.
I have created following 2 functions which does Saving & Retrieving of Data using NSUserDefault. Refer it and use accordingly.
func saveDataInUserDefault()
{
// *** init NSUserDefaults ***
let userDefaults = NSUserDefaults()
// *** Init a UIImage, you can use your UIImage instead ***
let img = UIImage.init(imageLiteral: "image")
// *** set values in UserDefault as well image ***
userDefaults.setObject("value of name textfield", forKey: "name")
userDefaults.setObject("value of position textfield", forKey: "position")
userDefaults.setObject("value of division textfield", forKey: "division")
userDefaults.setObject("value of route textfield", forKey: "route")
// *** convert image to NSData and store it ***
userDefaults.setObject(UIImageJPEGRepresentation(img, 1.0), forKey: "image")
// *** save all the changes to NSUserDefaults ***
userDefaults.synchronize()
}
func getDataFromUserDefaults()
{
// *** Now lets access all the stored data from user default ***
// *** init NSUserDefaults ***
let userDefaults = NSUserDefaults()
// *** to get normal objects use following ***
print(userDefaults.objectForKey("name"))
// *** to load image use following ***
let img = UIImage(data:userDefaults.objectForKey("image") as! NSData)
}
Iv'e got 2 ViewControllers, In the first one the user get the points and the high score label.
In the second ViewController, the code calculates if the user has broke the old high score, if yes - it changes, of course. BUT! when I quit the app and start playing again, the high score label show my last score and not the highest score.
Here is my code:
First ViewController:
let defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
defaults.synchronize()
highScore.text = String(stringInterpolationSegment: oldScore)
Second ViewController:
let defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
if score > oldScore {
defaults.setInteger(score, forKey: "oldScore")
defaults.synchronize()
var money = defaults.valueForKey("oldScore") as! Int
oldScore = money
} else {
defaults.setInteger(oldScore, forKey: "oldScore")
defaults.synchronize()
var money = defaults.valueForKey("oldScore") as! Int
oldScore = money
}
I also got var oldScore = Int() in the view controller code but outside the class of the view controller.
In addition, I have a "Switch" button that starts with state of "ON". But sometimes me/the user want to change it to off, how can I save it to be the user's choice after I quit the app and relaunch?
First of all check if NSUserDefault for oldScore is set. If it is not set only then initialise the oldScore, otherwise don't. Just fetch the value of oldScore and compare it with the new score and set the value accordingly
if (NSUserDefaults.standardUserDefaults().objectForKey(oldScore) == nil) {
oldScore = Int()
}
In your Second View Controller, first of all put NSUserDefault's oldScore's value into a variable and then check if it is equal to your Score. If it is only then set it like this :
let defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
var oldScoreCheck = defaults.valueForKey("oldScore") as! Int
if score > oldScoreCheck {
defaults.setInteger(score, forKey: "oldScore")
defaults.synchronize()
}
In your first view controller make the following change.
let defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
if defaults.integerForKey("oldScore") != nil
{
highScore.text = defaults.integerForKey("oldScore")
}
else
{
highScore.text = 0
}
There might be some changes required dependent on the variable type of highScore.
Hope this might be helpful.
According Apple's documentation you should register all default values before using them.
In AppDelegate in application:didFinishLaunchingWithOptions: add this code to register the key oldScore to have a reliable default value. A key switchState is also registered for the mentioned "Switch" button.
let defaults = NSUserDefaults.standardUserDefaults()
let defaultValues = ["oldScore" : 0, "switchState" : "ON"]
defaults.registerDefaults(defaultValues)
In the first view controller retrieve the high score value. If no value has been ever written to disk, the registered default value (0) is taken. You could read the value for the "Switch" button respectively.
let defaults = NSUserDefaults.standardUserDefaults()
let oldScore = defaults.integerForKey("oldScore")
let buttonState = defaults.stringForKey("switchState")
highScore.text = "\(oldScore)"
In the second view controller save the high score if changed
let defaults = NSUserDefaults.standardUserDefaults()
let oldScore = defaults.integerForKey("oldScore")
if score > oldScore {
defaults.setInteger(score, forKey: "oldScore")
defaults.synchronize()
oldScore = score
}