Thread 1: EXC_BAD_INSTRUCTION when encoding data in UserDefaults (Swift) - swift

Hi, I am trying to save data in Userdefaults but whenever I run this page of the app I am getting Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOC) as shown in the image.
Prior to this, I was getting the same exact error on the line beneath the one that I am getting it on right now, but now it is coming on this current line as seen in the image. How can I fix this to save my data every time the app launches?
var highScore = 0
var bronzeStatus = 0
ViewDidLoad:
let defaults = UserDefaults.standard
highScore = defaults.value(forKey: "Add1High") as! NSInteger!
bronzeStatus = defaults.value(forKey: "bronzeMed") as! NSInteger!
Underneath:
if correctNumber > highScore {
highScore = correctNumber
let defaults = UserDefaults.standard
defaults.setValue(highScore, forKey: "Add1High")
defaults.synchronize()
}
if highScore >= 15 {
let defaults = UserDefaults.standard
let bronzeAlert = UIAlertController(title: "New Medal!", message: "You earned a bronze medal!", preferredStyle: UIAlertControllerStyle.alert)
bronzeAlert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
self.present(scoreAlert, animated: true, completion: nil)
bronzeStatus = 1
defaults.setValue(bronzeStatus, forKey: "bronzeMed")
defaults.synchronize()
}

Try using
highScore = defaults.integer(forKey: "Add1High")
it converts the returned value to an NSInteger. If the value is an NSNumber, the result of -integerValue will be returned. If the value is an NSString, it will be converted to NSInteger if possible. If the value is absent or can't be converted to an integer, 0 will be returned. So no need to convert on your part.
Also while setting use
defaults.set(highScore, forKey: "Add1High")

Swift 3.0 code
this code work parfect..
var highScore = 0
var bronzeStatus = 0
ViewDidLoad:
//set integer type data
UserDefaults.standard.set(20, forKey: "Add1High")
UserDefaults.standard.set(30, forKey: "bronzeMed")
//Get integer type data
let defaults = UserDefaults.standard
highScore = defaults.integer(forKey: "Add1High")
bronzeStatus = defaults.integer(forKey: "bronzeMed")
print("\(highScore)\(bronzeStatus)") //2030

use this to check your userdefaults value exits or not
let defaults = UserDefaults.standard
if defaults.value(forKey: "Add1High") != nil{
highScore = defaults.value(forKey: "Add1High") as! NSInteger!
}
if defaults.value(forKey: "bronzeStatus") != nil{
bronzeStatus = defaults.value(forKey: "bronzeStatus") as! NSInteger!
}
Because you have condition
if correctNumber > highScore{}
so this part may execute or maybe not ,so you have to check for that

Related

Menu indexpath save UserDefaults swift

I want to save whichever indexpath I last clicked in the menu. He's recording indexpath right now. But if I choose indexpath, he's recording it. If I don't choose, it doesn't. How can I keep the previous record even if I don't select item from the menu?
let save11 = UserDefaults.standard.integer(forKey: "indexPath")
let yenindex = save11
self.menuView.setSelected(index: yenindex)
let userDefaults = UserDefaults.standard
userDefaults.removeObject(forKey: "indexPath")
menuView.didSelectItemAtIndexHandler = {(indexPath: Int) -> Void in
var placesdeger: String = ""
UserDefaults.standard.setValue(indexPath, forKey: "indexPath")
if indexPath == 0 {
let userDefaults = UserDefaults.standard
userDefaults.removeObject(forKey: "indexPath")
UserDefaults.standard.setValue(indexPath, forKey: "indexPath")
placesdeger = "Yatak Odası"
}
if indexPath == 1 {
let userDefaults = UserDefaults.standard
userDefaults.removeObject(forKey: "indexPath")
UserDefaults.standard.setValue(indexPath, forKey: "indexPath")
placesdeger = "Oturma Odası"
self.refreshData()
}
when ever you click on menu remove previous Userdefault value and set new user default value every time.
Put this code and get new index every time and if not selected then old value you will get in Userdefaults
let userDefaults = UserDefaults.standard
userDefaults.removeObject(forKey: "index")
userDefaults.set(i, forKey: "index")
EDIT1
USE THIS IN SOMEWHERE YOU DEFINE CONSTANT ONLY ONCE
let userDefaults = UserDefaults.standard
If you are using or any other method i dont know but if you get proper indexpath then this code will work
menuView.didSelectItemAtIndexHandler = {(indexPath: Int) -> Void in
var placesdeger: String = ""
userDefaults.removeObject(forKey: "indexPath")
if indexPath == 0 {
let userDefaults = UserDefaults.standard
UserDefaults.standard.setValue(indexPath, forKey: "indexPath")
placesdeger = "Yatak Odası"
}
if indexPath == 1 {
UserDefaults.standard.setValue(indexPath, forKey: "indexPath")
placesdeger = "Oturma Odası"
self.refreshData()
}

UserDefault is not saving the value

I have a survey form that appear only if the user still didn't answer survey every time the user launch the app. But even if I already answered the survey still its appearing. Here's how I'm doing it
//Get if questionaire is done
let defaults = UserDefaults.standard
if let questionaire_done = defaults.string(forKey: "questionaire_done") {
print(questionaire_done) // Some String Value
}else {
performSegue(withIdentifier: "questionaireSegue", sender: nil)
}
UserDefaults.standard.set("yes", forKey: "questionnaire_done") //set the questionnaire as done
if let questionaire_done = defaults.string(forKey: "questionaire_done")
has a different key to
UserDefaults.standard.set("yes", forKey: "questionnaire_done")
Spell the keys the same, or better still, use a constant string for the key.
Store the value in before segue (navigation)
//Get if questionaire is done
let defaults = UserDefaults.standard
if let questionaire_done = defaults.string(forKey: "questionnaire_done") {
print(questionaire_done) // Some String Value
}else {
defaults.set("yes", forKey: "questionnaire_done") //set the questionnaire as done
performSegue(withIdentifier: "questionaireSegue", sender: nil)
}
If you want to validate your condition then you like
let defaults = UserDefaults.standard
if let questionaire_done = defaults.string(forKey: "questionnaire_done"), questionaire_done == "yes" {
print(questionaire_done) // Some String Value
}else {
defaults.set("yes", forKey: "questionnaire_done") //set the questionnaire as done
performSegue(withIdentifier: "questionaireSegue", sender: nil)
}
Yes, the key value name should be always same but one more thing - you should write this after any "UserDefaults" operation - either read or write.
UserDefaults.standard.synchronize()
Example -
UserDefaults.standard.set("yes", forKey: "questionnaire_done")
UserDefaults.standard.synchronize()

Using UserDefaults to save a high score in swift

I"m trying to get a high score to save each time the player exits the app, but I'm struggling to get it to work and I'm confused as to where I'm making a mistake.
var gameSettings = Settings.sharedInstance
let HIGHSCORE = "HIGHSCORE"
if gameSettings.highScore < score{
gameSettings.highScore = score
UserDefaults.standard.set(gameSettings.highScore, forKey: HIGHSCORE)
}
if gameSettings.highScore >= score{
gameSettings.score = score
}
let gameOverHighScore = SKLabelNode()
gameOverHighScore.name = "gameOverHighScore"
gameOverHighScore.fontName = "Helvetica Neue UltraLight"
if let HIGHSCORE = UserDefaults.standard.value(forKey: HIGHSCORE) {
gameOverHighScore.text = "HIGHSCORE : \(HIGHSCORE)M"
}
gameOverHighScore.fontColor = SKColor.white
gameOverHighScore.position = CGPoint(x: 0, y: -175)
gameOverHighScore.fontSize = 70
gameOverHighScore.zPosition = 52
addChild(gameOverHighScore)
In if let HIGHSCORE = UserDefaults.standard.value(forKey: HIGHSCORE) {
gameOverHighScore.text = "HIGHSCORE : \(HIGHSCORE)M"
}
you are try find value in UserDefaults not by key HIGHSCORE, but by new value HIGHSCORE of type ANY. If you want to fix it, you can do like this:
if let HIGHSCORE = UserDefaults.standard.value(forKey: self. self.HIGHSCORE) as! Int {
gameOverHighScore.text = "HIGHSCORE : \(HIGHSCORE)M" }
or you can unwrap value in new value with another name. And don't forget to cast value to appropriate type or use
UserDefaults.standard.integer(forKey: self.HIGHSCORE)
Here is a simple example on how to do it:
let firebaseId = user.uid // Variable we want to save
UserDefaults.standard.set(firebase, forKey: "firebase") // Saving the variable with key "firebase"
And now to retrieve:
if let firebaseId = UserDefaults.standard.string(forKey: "firebase") {
print("Firebase ID: \(firebase)")
}
On your code, you are retrieving to HIGHSCORE, and you should be retrieving to something like gameSettings.highScore (Based on what I can infer from your code)

NSUserDefaults valueForKey error

I am trying to save a highscore in a simple game. I am new to swift 2 and not sure what I am doing wrong. i am getting the error that "Value of type 'int' has no member for 'valueForKey'. Here is my code as of my last unsuccesful attempt.
var highScoreDefault = NSUserDefaults.standardUserDefaults()
if(highScoreDefault.valueForKey("highScore") != nil){
highScore = highScore.valueForKey("highScore") as NSInteger! //error here
}
newFunc
score += 1
if (score > highScore){
highScore = score
var highScoreDefault = NSUserDefaults.standardUserDefaults()
highScoreDefault.setValue(highScore, forKey: "highScore")
highScoreDefault.synchronize()
}
highscoreLbl.text = "\(highScore)"
You have to save it like :NSUserDefaults.standardUserDefaults().setInteger(highScore, forKey: "highScore")
and retrieve it like : var highScore: Int = NSUserDefaults.standardUserDefaults().integerForKey("highScore")
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setValue(value, forKey: "highScore")
Apple recommends to only call synchronize() in special circumstances like when the app is about to exit.
The synchronize() method, which is automatically invoked at periodic
intervals, keeps the in-memory cache in sync with a user’s defaults
database.
Its very simple to set value in NSUserDefault
NSUserDefaults.standardUserDefaults().setInteger(yourScore, forKey: "highScore")
NSUserDefaults.standardUserDefaults().synchronize()
Try this one:
let highScoreDefault = NSUserDefaults.standardUserDefaults()
//Set
highScoreDefault.setInteger(yourInt, forKey: "intKey")
highScoreDefault. synchronize()
//Get
highScoreDefault.integerForKey("intKey")

EXC Bad Instruction

In was wondering why I keep getting this error message, EXC Bad Instruction could someone help me out and tell me why.
Here is the code.
func updateStocks() {
let stockManager:StockManagerSingleton = StockManagerSingleton.sharedInstance
stockManager.updateListOfSymbols(stocks)
//Repeat this method after 15 secs. (For simplicity of the tutorial we are not cancelling it never)
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(15 * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(),
{
self.updateStocks()
}
)
}
//4
func stocksUpdated(notification: NSNotification) {
let values = (notification.userInfo as! Dictionary<String,NSArray>)
let stocksReceived:NSArray = values[kNotificationStocksUpdated]!
stocks.removeAll(keepCapacity: false)
for quote in stocksReceived {
let quoteDict:NSDictionary = quote as! NSDictionary
let changeInPercentString = quoteDict["ChangeInPercent"] as! String
let changeInPercentStringClean: NSString = (changeInPercentString as NSString).substringToIndex((changeInPercentString as NSString).length-1)
stocks.append(quoteDict["symbol"] as! String,changeInPercentStringClean.doubleValue)
}
tableView.reloadData()
NSLog("Symbols Values updated :)")
}
}
The line with the error in it is,
let changeInPercentString = quoteDict["ChangeInPercent"] as! String
The error states that Swift attempted to unwrap a nil value, as you stated on this line
let changeInPercentString = quoteDict["ChangeInPercent"] as! String
Swift attempts to force setting the value of quoteDict["ChangeInPercent"] to a String, because you use as!, instead, you should use as?, which will set the value to nil if the value cannot be found
let changeInPercentString = quoteDict["ChangeInPercent"] as? String
You could set this to a default value by using the ?? operator. For example, if you wanted the default value to be 0.0%, you could use
let changeInPercentString = (quoteDict["ChangeInPercent"] as? String) ?? "0.0%"
The inherent problem is most likely either that quoteDict["ChangeInPercent"] does not exist, or quoteDict["ChangeInPercent"] is not a String - it may be an NSString or simply a Double value.
If you find out that it is supposed to be an NSString, for example, you will need to change how you cast the value
let changeInPercentString: NSString = (quoteDict["ChangeInPercent"] as? NSString) ?? "0.0%"