Delete key values for NSUserDefaults in Swift - ios

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

Related

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

Can't modify array stored in NSUserDefaults

In a class FirstViewController, I add an array with key rentedItems to the NSUserDefaults in the following lines:
let itemArray = [Item]()
let prefs:NSUserDefaults = NSUserDefaults.standardUserDefaults()
prefs.setObject(itemArray, forKey: "rentedItems")
Then, in another class SecondViewController, I try
var item: Item?
var prefs:NSUserDefaults = NSUserDefaults.standardUserDefaults()
func confirmPressed() {
prefs.arrayForKey("rentedItems")?.append(item)
}
This then gives the following error:
Cannot use mutating member on immutable value: function call returns immutable value. I saw a solution in SO here that gave me an idea of the problem, but NSUserDefaults being a default iOS class, I can't use the same solution as there. Any ideas?
You can't directly modify an array from defaults. Instead make a copy, and modify that. You can save that array to defaults afterwards. Simply try like this:
var array = prefs.arrayForKey("rentedItems")?.mutableCopy
array.append(item)
You will need to archive Your Custom Object Array into NSData then save it to NSUserDefaults and retrieve it from NSUserDefaults and unarchive it again. You can archive it like this:
var userDefaults = NSUserDefaults.standardUserDefaults()
let encodedData = NSKeyedArchiver.archivedDataWithRootObject(itemArray)
userDefaults.setObject(encodedData, forKey: "rentedItems")
userDefaults.synchronize()
And unarchive it like this
let decoded = userDefaults.objectForKey("rentedItems") as! NSData
let itemArray = NSKeyedUnarchiver.unarchiveObjectWithData(decoded) as! [Item]

Swift: Is not saving NSUserDefaults.standardUserDefaults values

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

Cannot retrieve data from NSUserDefaults into today extension (Swift)

I have a group of arrays that all contain a number of instances of a custom Task object that I have created. I am saving the arrays to NSUserDefaults as follows:
Custom Task Object
class Task:NSObject, NSCoding {
var name:String
var notes:String
var date:NSDate
var dateUse:Bool
var taskCompleted:Bool
init(name:String, notes:String, date:NSDate, dateUse:Bool, taskCompleted:Bool){
self.name = name
self.notes = notes
self.date = date
self.dateUse = dateUse
self.taskCompleted = taskCompleted
}
required init(coder decoder: NSCoder){
self.name = decoder.decodeObjectForKey("name") as! String
self.notes = decoder.decodeObjectForKey("notes") as! String
self.date = decoder.decodeObjectForKey("date") as! NSDate
self.dateUse = decoder.decodeObjectForKey("dateUse") as! Bool
self.taskCompleted = decoder.decodeObjectForKey("taskCompleted") as! Bool
}
func encodeWithCoder(coder: NSCoder) {
coder.encodeObject(self.name, forKey: "name")
coder.encodeObject(self.notes, forKey: "notes")
coder.encodeObject(self.date, forKey: "date")
coder.encodeObject(self.dateUse, forKey: "dateUse")
coder.encodeObject(self.taskCompleted, forKey: "taskCompleted")
}
}
Saving:
let defaults = NSUserDefaults(suiteName: "group.com.myGroupName")
let nowData = NSKeyedArchiver.archivedDataWithRootObject(nowTasks)
defaults!.setObject(nowData, forKey: "nowData")
Retrieving
let nowDataPull = defaults!.objectForKey("nowData") as? NSData
if let nowDataPull2 = nowDataPull{
let nowTasks2 = NSKeyedUnarchiver.unarchiveObjectWithData(nowDataPull2) as? [Task]
if let nowTasks21 = nowTasks2{
nowTasks = nowTasks21
}
}
The above method works fine for setting and retrieving data from the iPhone itself. However, this method does not work when trying to retrieve the data via the today extension.
When trying to retrieve from the today extension's .swift file I get the following errors:
Failed to inherit CoreMedia permissions from 52550: (null)
Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: '* -[NSKeyedUnarchiver
decodeObjectForKey:]: cannot decode object of class (MyAppName.Task)
for key (NS.objects); the class may be defined in source code or a
library that is not linked'
I know that the extension can read the data because when I call:
if (defaults?.objectForKey("nowData") != nil){
print("there is data")
}
I get the printed response..
I can successfully save an Integer and retrieve via the today extension, but not objectForKey
I have tried various other saving methods including .plist files, but nothing seems to work. The same errors keep occurring. Any input would be greatly appreciated!
another way is to fix the name of the class used for NSCoding. You simply have to use:
NSKeyedArchiver.setClassName("Task", forClass: Task.self before serializing
NSKeyedUnarchiver.setClass(Task.self, forClassName: "Task") before deserializing
wherever needed.
Looks like iOS extensions prefix the class name with the extension's name.
Set Object
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject("iOS", forKey: "userNameKey")
defaults.setInteger(25, forKey: "Age")
defaults.setBool(true, forKey: "UseTouchID")
defaults.setDouble(M_PI, forKey: "Pi")
Reading
let defaults = NSUserDefaults.standardUserDefaults()
let name = defaults.stringForKey("userNameKey")
Workaround:
So I have found a workaround (which is actually more efficient) for my problem. Because the decoding of [Task] was causing problems, I decided to go ahead and retrieve the data from an array that did not have objects inside of it, but rather just NSDate() instances. Because of this I can now save and access the important aspects of data that the today extension needs. I urge anyone else who is having issues with custom class decoding to try and simplify your data if at all possible in order to retrieve and use it in your extension. I am not exactly sure what the problem was or is, but retrieving simple data from an array stored in NSUserDefaults works without problems.
Hope all of this nonsense can help someone else out there!

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