120

Are the following two lines equivalent?

1. [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"example key"]

2. [[NSUserDefaults standardUserDefaults] setObject:nil forKey:@"example key"]

ma11hew28
  • 121,420
  • 116
  • 450
  • 651

3 Answers3

97

Yes, both lines of code are equivalent, both will result in nil read

id obj = [[NSUserDefaults standardUserDefaults] objectForKey:@"example key"];

NSUserDefaults will return nil if the key was not found. I would recommend to use the removeObjectForKey instead of setting it to nil.

here is how to test if setting key value to nil removed the key entry from NSUserDefaults standardUserDefaults.

NSArray *keys = [[[NSUserDefaults standardUserDefaults] dictionaryRepresentation] allKeys] copy];
   for(NSString *key in keys) {
       NSLog(@"Key Name: %@", key);
}
[keys release];

or simply dump the key/value dictionary of NSUserDefaults standardUserDefaults

NSLog(@"All contents of NSUserDefaults: %@", [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]);
pkamb
  • 33,281
  • 23
  • 160
  • 191
RocketMan
  • 4,289
  • 2
  • 26
  • 19
  • Yea, but if you set it to nil does it automatically `removeObjectForKey`? – ma11hew28 May 19 '11 at 19:35
  • not sure if setting it to 'nil' will remove the key entry in the [NSUserDefaults standardUserDefaults]. A quick test would be is to get 'allKeys' [[NSUserDefaults standardUserDefaults] allKeys] and iterate through the NSArrya of key names, find out if setting a key to nil does remove the key from the 'allKey' array. – RocketMan May 24 '11 at 15:03
  • 9
    the result is 'YES' both 'removeObjectForKey' and 'setObject:nil' will remove key @"example key" from [NSUserDefaults standardUserDefaults] – RocketMan May 25 '11 at 04:07
  • 9
    thanks! I confirmed this as well. Just to clarify, `setObject:nil` will also remove the object, not just its key. So, both functions cause exactly the same result. Also, if you remove (or set to nil) the only stored object (and key), the whole .plist file is deleted. – ma11hew28 May 31 '11 at 19:57
15

Swift 3.0

The below answer is no longer the case when I tested this. When set to nil the result is NSCFData being stored. Possibly an NSNull object reference, but I am not positive.

To completely remove a value for a key use UserDefaults.standard.removeObject(forKey: "YourDefault")

I tested with the following code:

UserDefaults.standard.set(["a", "b", "c"], forKey: "MyDefaults")
print("Test A: My saved defaults \(UserDefaults.standard.object(forKey: "MyDefaults"))")

UserDefaults.standard.set(nil, forKey: "MyDefaults")
print("Test B: My defaults set to nil \(UserDefaults.standard.object(forKey: "MyDefaults"))")

UserDefaults.standard.removeObject(forKey: "MyDefaults")
print("Test C: My defaults removed \(UserDefaults.standard.object(forKey: "MyDefaults"))")
Sean
  • 2,106
  • 2
  • 16
  • 24
  • Interesting, in Swift, when I type set(nil, forKey:...), and use "jump to definition", it takes me to the URL setter. The comment for that function says "-setURL:forKey is equivalent to -setObject:forKey: except that the value is archived to an NSData." This could explain why it is misbehaving - since there are two overloaded functions which accept nil, Swift has to choose one, but setURL doesn't behave the same. – Richard Venable Jun 01 '18 at 02:16
1

Swift 5.0 + iOS 11 and up

Both methods remove the value. Tried this in a playground:

import Foundation

let key = "Test"
let value = "test"
let defaults = UserDefaults.standard

func printUD() {
    print("UserDefaults after modification:\n")
    defaults.dictionaryRepresentation().forEach { print("\($0): \($1)\n") }
    print("-------------\n\n")
}

defaults.set(value, forKey: key); printUD()
defaults.set(nil, forKey: key); printUD()
defaults.set(value, forKey: key); printUD()
defaults.removeObject(forKey: key); printUD()

Prior to iOS 11 this will result in serializing nil into Data and throw an error.

Daniil Korotin
  • 720
  • 3
  • 14