I need a way to save key and value pairs in swift for my application. I am new to IOS programming, but I know Android and I am looking for something like shared preferences in android, but for swift. By "save," I mean that when the user quits out of the application, the key and value pairs are saved in the local data.
Swift 3.0
Saving Data:
let userDefaults = UserDefaults.standard
userDefaults.set(yourKey, forKey: "yourKey")
userDefaults.synchronize()
Reading Data:
if let yourVariable: AnyObject = UserDefaults.standard.object(forKey: "yourKey") as AnyObject? { }
What you are looking for is called "Userdefaults" - you can use them like this:
Saving Data:
let userDefaults = NSUserDefaults.standardUserDefaults()
userDefaults.setObject(variable, forKey: "yourKey")
userDefaults.synchronize()
Reading Data:
if let yourVariable: AnyObject = NSUserDefaults.standardUserDefaults().objectForKey("yourKey") {
....
Here you find more information:
https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/index.html
Working way for Swift 3+:
// Storing values
UserDefaults.standard.set(true, forKey: "KeyName") // Bool
UserDefaults.standard.set(1, forKey: "KeyName") // Integer
UserDefaults.standard.set("TEST", forKey: "KeyName") // setObject
// Retrieving values
UserDefaults.standard.bool(forKey: "KeyName")
UserDefaults.standard.integer(forKey: "KeyName")
UserDefaults.standard.string(forKey: "KeyName")
// Removing values
UserDefaults.standard.removeObject(forKey: "KeyName")
Related
I am trying to encode a struct
struct Configuration : Encodable, Decodable {
private enum CodingKeys : String, CodingKey {
case title = "title"
case contents = "contents"
}
var title : String?
var contents: [[Int]]?
}
into JSON to store in a local key of UserDefaults.standard. I have the following code:
let jsonString = Configuration(title: nameField.text, contents: newContents)
let info = ["row" as String: jsonString as Configuration]
print("jsonString = \(jsonString)")
//trying to save object
let defaults = UserDefaults.standard
let recode = try! JSONEncoder().encode(jsonString)
defaults.set(recode, forKey: "simulationConfiguration")
//end of saving local
The print returns:
jsonString = Configuration(title: Optional("config"), contents: Optional([[4, 5], [5, 5], [6, 5]]))
so I believe I am creating the object correctly. However, when I try and retrieve the key the next time I run the simulator I get nothing.
I put the following in AppDelegate and it always returns No Config.
let defaults = UserDefaults.standard
let config = defaults.string(forKey: "simulationConfiguration") ?? "No Config"
print("from app delegate = \(config.description)")
Any ideas? Thanks
Here you are saving a Data value (which is correct)
defaults.set(recode, forKey: "simulationConfiguration")
But here you are reading a String
defaults.string(forKey: "simulationConfiguration")
You cannot save Data, read String and expect it to work.
Let's fix your code
First of all you don't need to manually specify the Coding Keys. So your struct become simply this
struct Configuration : Codable {
var title : String?
var contents: [[Int]]?
}
Saving
Now here's the code for saving it
let configuration = Configuration(title: "test title", contents: [[1, 2, 3]])
if let data = try? JSONEncoder().encode(configuration) {
UserDefaults.standard.set(data, forKey: "simulationConfiguration")
}
Loading
And here's the code for reading it
if
let data = UserDefaults.standard.value(forKey: "simulationConfiguration") as? Data,
let configuration = try? JSONDecoder().decode(Configuration.self, from: data) {
print(configuration)
}
encode(_:) function of JSONEncoder returns Data, not String. This means when you need to get the Configuration back from UserDefaults you need to get data and decode them.
Here is example:
let defaults = UserDefaults.standard
guard let configData = defaults.data(forKey: "simulationConfiguration") else {
return nil // here put something or change the control flow to if statement
}
return try? JSONDecoder().decode(Configuration.self, from: configData)
you also don't need to assign value to all the cases in CodingKeys, the values is automatically the name of the case
if you are conforming to both, Encodable and Decodable, you can simply use Codable instead as it is combination of both and defined as typealias Codable = Encodable & Decodable
If you want an external dependency that saves a boat load of frustration, checkout SwifterSwift
Here's how I did it in two lines using their UserDefaults extension.
For setting:
UserDefaults.standard.set(object: configuration, forKey: "configuration")
For retrieving the object:
guard let configuration = UserDefaults.standard.object(Configuration.self, with: "configuration") else { return }
print(configuration)
That's about it..!!
Basically your UserDefault stored property will be look something like this,
private let userDefaults = UserDefaults.standard
var configuration: Configuration? {
get {
do {
let data = userDefaults.data(forKey: "configuration_key")
if let data {
let config = try JSONDecoder().decode(User.self, from: data)
return config
}
} catch let error {
print("Preference \(#function) json decode error: \(error.localizedDescription)")
}
return nil
} set {
do {
let data = try JSONEncoder().encode(newValue)
userDefaults.set(data, forKey: "configuration_key")
} catch let error {
print("Preference \(#function) json encode error: \(error.localizedDescription)")
}
}
}
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()
I want to know how to remove both key and value in NSUserDefaults . removeobjectforkey only removes the value ?
removeObjectForKey(string)
Swift 3
to add value in NSUserDefault
integer
UserDefaults.standard.integer(forKey: "key")
a dictionary
UserDefaults.standard.set(Dictvariable, forKey: "key")
get value
from integer
key value = UserDefaults.standard.integer(forKey: "key")
get value from dictionary
let result = UserDefaults.standard.value(forKey: "key") as? [String: String] ?? [String: String]()
to remove(i not tried this u can try this take it from stackoverflow 99% its work)
UserDefaults.standard.removeObject(forKey: "yourKey")
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")
I want to get a swift dictionary from NSUserDefaults as the format that I've saved before. I've saved the dictionary as [String:String] format, but while I'm getting the dictionary with dictionaryForKey(key) method I got [String:AnyObject]?. How can I convert [String:AnyObject]? to [String:String] or how can I get the dictionary in right format?
Saving to NSUserDefaults
var tasks: Dictionary<String,String> = [:]
let defaults = NSUserDefaults.standardUserDefaults()
let key = "key"
defaults.setObject(tasks, forKey: key)
defaults.synchronize()
Getting from NSUserDefaults
let defaults = NSUserDefaults.standardUserDefaults()
let key = "ananZaa"
let incomingArray = defaults.dictionaryForKey(key)
If you've registered it with a default value so it never can be nil, just downcast it to the proper type
let defaults = NSUserDefaults.standardUserDefaults()
let key = "ananZaa"
let incomingDictionary = defaults.objectForKey(key) as! Dictionary<String,String>