Swift: Is not saving NSUserDefaults.standardUserDefaults values - ios

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 :)

Related

UserDefaults not working with MSMessagesAppViewController

I am trying to save data to UserDefaults using an UIAlertController , but the code fails to retrieve the data.
Retrieve the Data
func displayCreatedPhrases(){
phrases = uDefaults.stringArray(forKey: "createdPhrases") ?? [String]()
print(phrases)
}
Setting the Data
self.uDefaults.set(textfield.text, forKey: "createdPhrases")
self.uDefaults.synchronize()
print("Saved the data!")
self.phraseTableView.reloadData()
You are setting the string as a value for key 'createdPhrases' and then asking uDefaults to return an array of string?
func displayCreatedPhrases() {
phrases = uDefaults.value(forKey: "createdPhrases") as? String
print(phrases)
}
The above code should work for you.
Also no need to use below line (Link to UserDefaults synchronize)
self.uDefaults.synchronize()
Reason:
textfield.text is of type String? and not [String]. In your code, you're saving the data as a String value and retrieving it as an [String] value. That's the reason, retrieving the data doesn't work.
Solution:
func displayCreatedPhrases(){
phrases = uDefaults.string(forKey: "createdPhrases") ?? ""
print(phrases)
}
Also, phrases must be of type String.

Conditional cast from string to string always succeds in swift 3

func resetUserDefaults() {
let userDefaults = UserDefaults.standard
let dict = userDefaults.dictionaryRepresentation()
for (key,_) in dict {
if let key = key as? String {
userDefaults.removeObject(forKey: key)
} else {
#if DEBUG
NSLog("\(key)")
#endif
}
}
}
I'm getting this warning. can anyone suggest me how to avoid this warnoing
All keys in UserDefaults must be of type String. So key is declared as a String. So attempting to cast it to a String is pointless. Hence the warning.
All you need is:
func resetUserDefaults() {
let userDefaults = UserDefaults.standard
let dict = userDefaults.dictionaryRepresentation()
for (key,_) in dict {
userDefaults.removeObject(forKey: key)
}
}
There is no need to cast something to the type that it is already known (to the compiler) to have.
Just remove the whole condition and use your key directly.
Since the keys in the UserDefault should of type String, casting the key to string is of no use, and hence you are getting this warning.
func resetUserDefaults() {
let userDefaults = UserDefaults.standard
let dict = userDefaults.dictionaryRepresentation()
for (key, _) in dict {
userDefaults.removeObject(forKey: key)
}
}
It will always show waring because dictionaryRepresentation() return [String : Any].
So when you cast from string to string it will definitely show warning.
for more see this -> https://developer.apple.com/documentation/foundation/userdefaults/1415919-dictionaryrepresentation
I had the same issue with a private function in Swift 5 and I found a solution working for me.
The solution was to change the value to optional.
I added a question mark after the type I was looking for. (as String"?")
You can see an example here :
private func doSomeThing(completion: #escaping (String) -> ()) {
let Something = somethingElse;
if let anoterThing = something as String?{
completion(anoterThing)
}else{
completion("Error at private func doSomeThing")
}
}
You can find more pieces of information here:
https://docs.swift.org/swift-book/LanguageGuide/OptionalChaining.html
Swift: difference as String? vs. as? String
Downcasting in Swift with as and as?
Best Regards

UserDefault always return nil

UserDefaults are not working in my App. Please find the below code under AppDelegate file.
let sharingData = UserDefaults.init(suiteName: "group.macuser79.xxx");
sharingData?.set("vincenzo", forKey:"username");
sharingData?.synchronize();
In the InterfaceController of the app to Watch, to be able to retrieve the value so I did this:
override func awake(withContext context: Any?) {
let sharingData = UserDefaults.init(suiteName: "group.macuser79.xxx");
let username = sharingData?.object(forKey: "username");
print("Value username \(username)");
}
Please let me know, what I'm doing wrong!
In Swift3 UserDefaults made much smarter to obtained stored value. In below line, you are storing String value without specifying it!:
sharingData?.set("vincenzo", forKey:"username");
So, in order to get that, you need to write like below:
let username = sharingData?.string(forKey: "username");
print("Value username \(username)");
}
This is much more better context in getting values based on you Store.
Try this instead:
let defaults = UserDefaults.standard
defaults.set("group.macuser79.xxx", forKey:"username")
defaults.synchronize()
To access the store:
let defaults = UserDefaults.standard
let username = defaults.string(forKey: "username")
I admit that I haven't tried to init() my own UserDefaults instance before, but the standard instance of it, which is made into a singleton by iOS, is good practice to use.
Also, don't forget to unwrap the optional properly.
To set:
UserDefaults(suiteName: "group.macuser79.xxx")?.set("vincenzo", forKey: "username")
To access:
UserDefaults(suiteName: "group.macuser79.xxx")!.string(forKey: "username")

Delete key values for NSUserDefaults in Swift

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")

How do I register a plist to NSUserDefaults?

What I'm trying to do is store my initial user defaults in a plist and then read them into NSUserDefaults when the application loads for the first time.
I've found a couple of posts which have helped me thus far however I can't seem to find an answer as to why I'm finding nil while unwrapping. Obviously I'm missing something, so my question is:
How do I properly register a plist to NSUserDefaults?
I've created a plist with my default settings. I'd like to read from the plist and register them into NSUserDefaults.
settings.plist
ViewController.swift
class ViewController: UIViewController {
let userDefaults = NSUserDefaults.standardUserDefaults()
override func viewDidLoad() {
super.viewDidLoad()
let prefs = NSBundle.mainBundle().pathForResource("Settings", ofType: "plist")
let dict = NSDictionary(contentsOfFile: prefs!)
if let dictionary = dict {
println("Contents of file unwrapped: \(dictionary)") // <---------
let defaults : NSDictionary! = dictionary.valueForKey("Root") as? NSDictionary
println("defaults: \(defaults)") // <---------
userDefaults.registerDefaults(defaults as! [NSObject : AnyObject])
userDefaults.synchronize()
}
if let unwrapDict = dict {
var myValue = unwrapDict.objectForKey("Boolean Switch 1") as! Bool
println("pulled from pList \(myValue)")
}
}
}
I'm sure you've noticed that I am looking for the key 'Root' from my plist...
let defaults : NSDictionary! = dictionary.valueForKey("Root") as? NSDictionary
I have also tried passing it other values like "Boolean Switch 1" and casting to different types. But nothing I try changes the outcome.
Here's my console output from the two println() logs.
After a day of messing with this code I was able to finally get my plist entered into NSUserDefaults. I wasn't satisfied with the final outcome because I noticed that the registerDefaults wasn't actually doing anything.
So I decided to post my working code on Code Review to see if there were any parts of my code that weren't necessary. It turns out that registerDefualts indeed was not necessary, here's an excerpt from the Alex's answer to my question.
This line:
userDefaults.registerDefaults(dict as! [NSObject : AnyObject]) does
not actually set the information on the NSUserDefaults storage file on
disk. All it does is tell NSUserDefaults the default values to be used
when a key doesn't yet exist on disk.
So having said all of that, I'll post the working code. I should note, as it was pointed out to me by nhgrif, that the ViewController is really not the place to put this code and a better place is in the appDelegate in application(_:didFinishLaunchingWithOptions:).
ViewController:
class ViewController: UIViewController {
let userDefaults = NSUserDefaults.standardUserDefaults()
override func viewDidLoad() {
super.viewDidLoad()
let prefs = NSBundle.mainBundle().pathForResource("Settings", ofType: "plist")
let dict = NSDictionary(contentsOfFile: prefs!)
userDefaults.setObject(dict, forKey: "defaults")
userDefaults.synchronize()
// this just toggles the aBool value
if let defaults = userDefaults.valueForKey("aBool") as? NSNumber {
if defaults as NSObject == 1 {
println("inside the conditional: \(defaults)")
userDefaults.setValue(0, forKey: "aBool")
userDefaults.synchronize()
println("Setting aBool to true")
} else {
userDefaults.setValue(1, forKey: "aBool")
userDefaults.synchronize()
println("setting aBool to false")
}
}
}
}
According to Apple document, If you don't change any value on settings, Values reading from NSUserDefaults are nil or 0. In your code, When you read a value from NSUserDefaults, you should set it a default value.

Resources