NSUserDefaults has integerForKey:, setInteger:forKey: and stringForKey:, but does not have setString:forKey:.
How do you set a string to NSUserDefaults? It has setObject:forKey: but, in Swift, String is a struct. Is it ok to use setObject:forKey: to store a string?
update: Xcode 13.2.1 • Swift 5.5.2
let string = "Hello World"
UserDefaults.standard.set(string, forKey: "string")
if let loadedString = UserDefaults.standard.string(forKey: "string") {
print(loadedString) // "Hello World"
}
The nice thing about Swift is that it allows to you to easily extend the language. You can create your own date(forKey:) extending UserDefaults to create an instance method as follow:
extension UserDefaults {
func date(forKey defaultName:String) -> Date? {
object(forKey: defaultName) as? Date
}
}
let userName = "Chris Lattner"
let userAddress = "1 Infinite Loop, Cupertino, CA 95014, United States"
let userDOB = DateComponents(calendar: .init(identifier: .gregorian), year: 1978).date!
UserDefaults.standard.set(userName, forKey: "userName")
UserDefaults.standard.set(userAddress, forKey: "userAddress")
UserDefaults.standard.set(userDOB, forKey: "userDOB")
let loadedUserName = UserDefaults.standard.string(forKey: "userName")
let loadedUserAddress = UserDefaults.standard.string(forKey: "userAddress")
let loadedUserDOB = UserDefaults.standard.date(forKey: "userDOB")
print(loadedUserName ?? "nil") // "Chris Lattner"
print(loadedUserAddress ?? "nil") // "1 Infinite Loop, Cupertino, CA 95014, United States"
print(loadedUserDOB?.description(with: .init(identifier: "en_US")) ?? "nil") // "Sunday, January 1, 1978 at 12:00:00
Swift 3 removed .setObject. Use .set instead. For example:
// Create UserDefaults
let defaults = UserDefaults.standard
// Save String value to UserDefaults
// Using defaults.set(value: Any?, forKey: String)
defaults.set("Some string you want to save", forKey: "savedString")
// Get the String from UserDefaults
if let myString = defaults.string(forKey: "savedString") {
print("defaults savedString: \(myString)")
}
The reason that setObject can be used to apply a string is found in the discussion of the reference:
Since Swift String is bridged to NSString, the usage of setObject is valid. However as the other types mentioned are not accepted in NSUserDefaults using the setObject setter; they have their own convenience setters.
Notwithstanding this, almost anything one can think of can be serialized and placed into NSUserDefaults using setObject with an NSData argument (as noted elsewhere on SO).
You can definitly use setObject:forKey:, the NSDictionary method or even setValue:forkey: which is a KVC method.
It'll work just fine.
Related
I'm trying to save key value in the NSUserDefaults but is not been save. Here is my code:
func saveData() {
let userDefaults = NSUserDefaults.standardUserDefaults()
userDefaults.setObject("blablabla", forKey:"data")
userDefaults.synchronize()
}
Any of you knows why this data is not been save?
I'll really appreciate your help.
Swift 2.x:
According with Apple sources:
public func objectForKey(defaultName: String) -> AnyObject?
to retrieve your value you could use:
if let value = userDefaults.objectForKey("data") {
// do whatever you want with your value
// P.S. value could be numeric,string,..
}
I think you are doing it wrong, try like this:
let userDefaults = NSUserDefaults.standardUserDefaults()
userDefaults.setObject("blablabla", forKey:"data")
let defaults = NSUserDefaults.standardUserDefaults()
if let name = defaults.stringForKey("data") {
print(name)
}
You won't be able to access a string with dictionaryForKey because string is not a dictionary value type. Let me know if you need any further help.
You won't be able to access a string with 'dictionaryForKey' because a string is not a dictionary value type. You'll need to use:
if let savedString = userDefaults.stringForKey("data") {
print(savedString)
}
If you have any further questions feel free to let me know :)
How to delete data from NSUserDefaults? There is quite a few answers how to do it in Objective C, but how about Swift?
So I tried this:
let defaults = NSUserDefaults.standardUserDefaults()
defaults.removeObjectForKey("myKey")
Didn't work. Maybe what I really want to delete is not NSUserDefaults?
This is how I save data:
class MySavedData: NSObject, NSCoding {
var image: String
init(name: String, image: String) {
self.image = image
}
required init(coder aDecoder: NSCoder) {
image = aDecoder.decodeObjectForKey("image") as! String
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(image, forKey: "image")
}
}
class ViewController: <...> {
var myData = [MySavedData]() //Later myData gets modified and then function save() is called
func save() {
let savedData = NSKeyedArchiver.archivedDataWithRootObject(myData)
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(savedData, forKey: "myKey")
}
}
EDIT: Just to clear some things - data that is being saved is small (not even close to 100kb)
And maybe I am saving data not to NSUserDefaults (I am new to programming), so here is how I get it (load):
let defaults = NSUserDefaults.standardUserDefaults()
if let savedData = defaults.objectForKey("myData") as? NSData {
myData = NSKeyedUnarchiver.unarchiveObjectWithData(savedData) as! [UserLogin]
}
removeObjectForKey is the right way to go.
This will remove the value for the selected key. The following code sets a string value for a key in NSUserDefaults, prints it and then uses removeObjectForKey to remove and print the key value again. After removeObjectForKey the value is nil.
let prefs = NSUserDefaults.standardUserDefaults()
var keyValue = prefs.stringForKey("TESTKEY")
print("Key Value not set \(keyValue)")
let strHello = "HELLO WORLD"
prefs.setObject(strHello, forKey: "TESTKEY")
keyValue = prefs.stringForKey("TESTKEY")
print("Key Value \(keyValue)")
prefs.removeObjectForKey("TESTKEY")
keyValue = prefs.stringForKey("TESTKEY")
print("Key Value after remove \(keyValue)")
Returns:
Key Value not set nil
Key Value Optional("HELLO WORLD")
Key Value after remove nil
Update Swift 3:
let prefs = UserDefaults.standard
keyValue = prefs.string(forKey:"TESTKEY")
prefs.removeObject(forKey:"TESTKEY")
The code you have written will work fine, but NSUserDefaults synchronise at certain time interval.
As you want that should reflect in NSUserDefaults immediately ,so u need to write synchronise
let defaults = NSUserDefaults.standardUserDefaults()
defaults.removeObjectForKey("myKey")
defaults.synchronize()
Try This
NSUserDefaults.standardUserDefaults().removePersistentDomainForName(NSBundle.mainBundle().bundleIdentifier!)
for Swift 3
UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!)
But this will clear all values from NSUserDefaults.careful while using.
Removing UserDefaults for key in swift 3, based upon the top answer, just slightly different syntax:
UserDefaults.standard.removeObject(forKey: "doesContractExist")
Swift 4.x Remove all key in UserDefaults
let defaults = UserDefaults.standard
let dictionary = defaults.dictionaryRepresentation()
dictionary.keys.forEach
{ key in defaults.removeObject(forKey: key)
}
Use following for loop:
for key in NSUserDefaults.standardUserDefaults().dictionaryRepresentation().keys {
NSUserDefaults.standardUserDefaults().removeObjectForKey(key.description)
}
I would go for a solution which setting the value to nil for a key.
Swift 3
UserDefaults.standard.set(nil, forKey: "key")
Swift 2.x
NSUserDefaults.standardUserDefaults().setValue(nil, forKey: "key")
NOTE: that is a clear and straight statement, but bear in mind there is a limit to store information in NSUserDefaults, it is definitely not the right place to store large binary files (like e.g. images) – for that there is a Documents folder. however it is not defined how big the var image: String which you encode/decode.
To nuke all UserDefaults keys, you can use the following code in Swift 3.x:
UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!)
In Swift 5.0, iOS 15 below single line of code is enough.
UserDefaults.standard.dictionaryRepresentation().keys.forEach(defaults.removeObject(forKey:))
Or try this
if let appDomain = Bundle.main.bundleIdentifier {
UserDefaults.standard.removePersistentDomain(forName: appDomain)
}
func remove_pref(remove_key : String){
UserDefaults.standard.removeObject(forKey: remove_key)
UserDefaults.standard.synchronize()
}
Update code for Swift :
Used below line of code to Delete key values for NSUserDefaults in Swift
UserDefaults.standard.setValue(nil, forKey: "YouEnterKey")
I'm trying to save a variable in Xcode so that it saves even after the app has closed, how ever when I access it I do it from a several different classes and files, and I change the value of the variable when I access it. Therefore similar threads do not completely apply, the value to be stored is a string and here is the code I have up until now:
var defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(Token, forKey: "") as! String
I believe this is the correct format, but I don't know how to call it to change it because when I try I get an error message saying expected declaration.
Anyway any help would be very much appreciated.
First of all you have to specify an unique key to store the variable (in the example MyKey ).
In AppDelegate > applicationDidFinishLaunching register the key with a default value.
The benefit is you can use a non-optional variable and you have a defined default value.
let defaults = UserDefaults.standard
let defaultValue = ["MyKey" : ""]
defaults.register(defaults: defaultValue)
Now you can from everywhere read the value for the key
let defaults = UserDefaults.standard
let token = defaults.string(forKey: "MyKey")
and save it
let defaults = UserDefaults.standard
defaults.set(token, forKey: "MyKey")
Swift 3
(thanks to vadian's answer)
In AppDelegate > applicationDidFinishLaunching :
let defaults = UserDefaults.standard
let defaultValue = ["myKey" : ""]
defaults.register(defaults: defaultValue)
to save a key:
let defaults = UserDefaults.standard
defaults.set("someVariableOrString", forKey: "myKey")
defaults.synchronize()
to read a key:
let defaults = UserDefaults.standard
let token = defaults.string(forKey: "myKey")
Let's say you have a string variable called token
To save/update the stored value on the device:
NSUserDefaults.standardUserDefaults().setObject(token, forKey: "mytoken")
NSUserDefaults.standardUserDefaults().synchronize()
In the code above I made sure to give the key a value ("mytoken"). This is so that we later can find it.
To read the stored value from the device:
let token = NSUserDefaults.standardUserDefaults().objectForKey("mytoken") as? String
Since the method objectForKey returns an optional AnyObject, I'll make sure to cast it to an optional String (optional meaning that it's either nil or has a value).
Add default.synchronize() after setting value.
I have a textField for the user to input their name.
#IBAction func nameTextField(sender: AnyObject) {
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject("\(nameTextField)", forKey: "userNameKey")
}
Then I recall the inputted name in ViewDidLoad with:
NSUserDefaults.standardUserDefaults().stringForKey("userNameKey")
nameLabel.text = "userNameKey"
What am I doing wrong? Result is simply "userNameKey" every time. I'm new to this, thanks!
You just have to assign the result returned by nsuserdefaults method to your nameLabel.text. Besides that stringForKey returns an optional so I recommend using the nil coalescing operator to return an empty string instead of nil to prevent a crash if you try to load it before assigning any value to the key.
func string(forKey defaultName: String) -> String?
Return Value For string values, the string associated with the
specified key. For number values, the string value of the number.
Returns nil if the default does not exist or is not a string or number
value.
Special Considerations
The returned string is immutable, even if the value you originally set was a mutable string.
You have to as follow:
UserDefaults.standard.set("textToSave", forKey: "userNameKey")
nameLabel.text = UserDefaults.standard.string(forKey: "userNameKey") ?? ""
What you need to do is:
#IBAction func nameTextField(sender: AnyObject) {
let defaults = NSUserDefaults.standardUserDefaults()
defaults.set(yourTextField.text, forKey: "userNameKey")
}
And later in the viewDidLoad:
let defaults = NSUserDefaults.standardUserDefaults()
let yourValue = defaults.string(forKey: "userNameKey")
nameLabel.text = yourValue
I'm having issues when trying to pass data to my Apple Watch app through NSUserDefaults from my app. Whenever I try to retrieve the array that is stored, I am getting the error 'String' is not identical to 'AnyObject'.
I've been trying to figure out a solution but I can't work out what the issue is since I am using the same method elsewhere in my app and it works without issue.
Here is what I have in the Apple Watch part:
var defaults = NSUserDefaults(suiteName: "group.AffordIt")
tempNames = defaults?.objectForKey("namesWatch") as NSArray
tempDates = defaults?.objectForKey("datesWatch") as NSArray
tempAmounts = defaults?.objectForKey("valuesWatch") as NSArray
And the containing app part:
defaults?.setObject(names, forKey: "namesWatch")
defaults?.setObject(dates, forKey: "datesWatch")
defaults?.setObject(values, forKey: "valuesWatch")
names, dates and values are String arrays.
Any ideas?
IMO your problem is, that you try to cast an optional value, e.g.
if let names = defaults.objectForKey("namesWatch") as? NSArray
{
tempNames = names
}
Probably this SO question is related: Swift NSUserDefaults NSArray using objectForKey.
You need to cast the objects you are retrieving from your collection as being Strings:
defaults?.setObject(names, forKey: "namesWatch") as? String
defaults?.setObject(dates, forKey: "datesWatch") as? String
defaults?.setObject(values, forKey: "valuesWatch") as? String
let namesStringArray = ["John","Mary"]
let datesStringArray = ["May 21, 2009, 11:10 PM"]
let doublesStringArray = ["1.5","2.2","3.3"]
if let defaults = NSUserDefaults(suiteName: "group.AffordIt") {
defaults.setObject(namesStringArray , forKey: "namesWatch")
defaults.setObject(datesStringArray, forKey: "datesWatch")
defaults.setObject(doublesStringArray, forKey: "valuesWatch")
}
let defaults = NSUserDefaults(suiteName: "group.AffordIt")
if let tempNames = defaults!.stringArrayForKey("namesWatch") {
println(tempNames) // ["John", "Mary"]
}
if let tempDates = defaults!.stringArrayForKey("datesWatch") {
println(tempDates) // ["May 21, 2009, 11:10 PM"]
}
if let tempAmounts = defaults!.stringArrayForKey("valuesWatch") {
println(tempAmounts) // ["1.5", "2.2", "3.3"]
}