[ios] NSUserDefaults - How to tell if a key exists

I'm working on a small iPhone app, and I am using NSUserDefaults as my data persistence. It only has to keep track of a few things, such as some names and some numbers so I figure I might as well keep it simple.

I found this page for some reference, but I don't think it can answer my question. Basically, I want to be able to check if a value (or a key) already exists in the NSUserDefaults and then do something accordingly.

Some examples: The app starts up, if this is the first time it starts up it outputs an alert saying welcome. To tell if this is first time it has opened it reads the UserDefaults and checks.

Example 2: It says, "Hello [Name]", where Name is something you have entered. If you have opened the app and there is no name, it should say "Hello World." I need to check if you have entered a name already and act accordingly. The name would be stored in NSUserDefaults.

Some help here? I'd really appreciate it!

This question is related to ios objective-c iphone nsuserdefaults

The answer is


I just went through this, and all of your answers helped me toward a good solution, for me. I resisted going the route suggested by, just because I found it hard to read and comprehend.

Here's what I did. I had a BOOL being carried around in a variable called "_talkative".

When I set my default (NSUserDefaults) object, I set it as an object, as I could then test to see if it was nil:

//converting BOOL to an object so we can check on nil
[defaults setObject:@(_talkative) forKey:@"talkative"];

Then when I went to see if it existed, I used:

if ([defaults objectForKey:@"talkative"]!=nil )
  {

Then I used the object as a BOOL:

if ([defaults boolForKey:@"talkative"]) {
 ...

This seems to work in my case. It just made more visual sense to me.


Swift version to get Bool?

NSUserDefaults.standardUserDefaults().objectForKey(DefaultsIsGiver) as? Bool

In Swift3, I have used in this way

var hasAddedGeofencesAtleastOnce: Bool {
    get {
        return UserDefaults.standard.object(forKey: "hasAddedGeofencesAtleastOnce") != nil
    }
}

The answer is great if you are to use that multiple times.

I hope it helps :)


The objectForKey: method will return nil if the value does not exist. Here's a simple IF / THEN test that will tell you if the value is nil:

if([[NSUserDefaults standardUserDefaults] objectForKey:@"YOUR_KEY"] != nil) {
    ...
}

Swift 3 / 4:

Here is a simple extension for Int/Double/Float/Bool key-value types that mimic the Optional-return behavior of the other types accessed through UserDefaults.

(Edit Aug 30 2018: Updated with more efficient syntax from Leo's suggestion.)

extension UserDefaults {
    /// Convenience method to wrap the built-in .integer(forKey:) method in an optional returning nil if the key doesn't exist.
    func integerOptional(forKey: String) -> Int? {
        return self.object(forKey: forKey) as? Int
    }
    /// Convenience method to wrap the built-in .double(forKey:) method in an optional returning nil if the key doesn't exist.
    func doubleOptional(forKey: String) -> Double? {
        return self.object(forKey: forKey) as? Double
    }
    /// Convenience method to wrap the built-in .float(forKey:) method in an optional returning nil if the key doesn't exist.
    func floatOptional(forKey: String) -> Float? {
        return self.object(forKey: forKey) as? Float
    }
    /// Convenience method to wrap the built-in .bool(forKey:) method in an optional returning nil if the key doesn't exist.
    func boolOptional(forKey: String) -> Bool? {
        return self.object(forKey: forKey) as? Bool
    }
}

They are now more consistent alongside the other built-in get methods (string, data, etc.). Just use the get methods in place of the old ones.

let AppDefaults = UserDefaults.standard

// assuming the key "Test" does not exist...

// old:
print(AppDefaults.integer(forKey: "Test")) // == 0
// new:
print(AppDefaults.integerOptional(forKey: "Test")) // == nil

"objectForKey will return nil if it doesn't exist." It will also return nil if it does exist and it is either an integer or a boolean with a value of zero (i.e. FALSE or NO for the boolean).

I've tested this in the simulator for both 5.1 and 6.1. This means that you cannot really test for either integers or booleans having been set by asking for "the object". You can get away with this for integers if you don't mind treating "not set" as if it were "set to zero".

The people who already tested this appear to have been fooled by the false negative aspect, i.e. testing this by seeing if objectForKey returns nil when you know the key hasn't been set but failing to notice that it also returns nil if the key has been set but has been set to NO.

For my own problem, that sent me here, I just ended up changing the semantics of my boolean so that my desired default was in congruence with the value being set to NO. If that's not an option, you'll need to store as something other than a boolean and make sure that you can tell the difference between YES, NO, and "not set."


As mentioned above it wont work for primitive types where 0/NO could be a valid value. I am using this code.

NSUserDefaults *defaults= [NSUserDefaults standardUserDefaults];
if([[[defaults dictionaryRepresentation] allKeys] containsObject:@"mykey"]){

    NSLog(@"mykey found");
}

Extend UserDefaults once to don't copy-paste this solution:

extension UserDefaults {

    func hasValue(forKey key: String) -> Bool {
        return nil != object(forKey: key)
    }
}

// Example
UserDefaults.standard.hasValue(forKey: "username")

Try this little crumpet:

-(void)saveUserSettings{
NSNumber*   value;

value = [NSNumber numberWithFloat:self.sensativity];
[[NSUserDefaults standardUserDefaults] setObject:value forKey:@"sensativity"];
}
-(void)loadUserSettings{
    NSNumber*   value;
    value = [[NSUserDefaults standardUserDefaults] objectForKey:@"sensativity"];
    if(value == nil){
        self.sensativity = 4.0;
    }else{
        self.sensativity = [value floatValue];
    }
}

Treat everything as an object. Seems to work for me.


Swift 3.0

if NSUserDefaults.standardUserDefaults().dictionaryRepresentation().contains({ $0.0 == "Your_Comparison_Key" }){
                    result = NSUserDefaults.standardUserDefaults().objectForKey(self.ticketDetail.ticket_id) as! String
                }

Examples related to ios

Adding a UISegmentedControl to UITableView Crop image to specified size and picture location Undefined Symbols error when integrating Apptentive iOS SDK via Cocoapods Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Autoresize View When SubViews are Added Warp \ bend effect on a UIView? Speech input for visually impaired users without the need to tap the screen make UITableViewCell selectable only while editing Xcode 12, building for iOS Simulator, but linking in object file built for iOS, for architecture arm64

Examples related to objective-c

Adding a UISegmentedControl to UITableView Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Warp \ bend effect on a UIView? Use NSInteger as array index Detect if the device is iPhone X Linker Command failed with exit code 1 (use -v to see invocation), Xcode 8, Swift 3 ITSAppUsesNonExemptEncryption export compliance while internal testing? How to enable back/left swipe gesture in UINavigationController after setting leftBarButtonItem? Change status bar text color to light in iOS 9 with Objective-C

Examples related to iphone

Detect if the device is iPhone X Xcode 8 shows error that provisioning profile doesn't include signing certificate Access files in /var/mobile/Containers/Data/Application without jailbreaking iPhone Certificate has either expired or has been revoked Missing Compliance in Status when I add built for internal testing in Test Flight.How to solve? cordova run with ios error .. Error code 65 for command: xcodebuild with args: "Could not find Developer Disk Image" Reason: no suitable image found iPad Multitasking support requires these orientations How to insert new cell into UITableView in Swift

Examples related to nsuserdefaults

How can I use UserDefaults in Swift? How to save local data in a Swift app? how to save and read array of array in NSUserdefaults in swift? Attempt to set a non-property-list object as an NSUserDefaults iOS: How to store username/password within an app? Save string to the NSUserDefaults? How to store custom objects in NSUserDefaults NSUserDefaults - How to tell if a key exists Clearing NSUserDefaults