NSUserDefaults & Swift

What is NSUserDefaults?

NSUserDefaults is a class that allows simple storage of different data types.  It is ideal for small bits of information you need to persist between app launches or device restarts.

NSUserDefaults supports the following data types:

  • NSString
  • NSNumber
  • NSDate
  • NSArray
  • NSDictionary
  • NSData

 

When to use it

NSUserDefaults should be used to store small amounts of data.  In my personal app Teal, I use NSUserDefaults to save the user’s last viewed tally or event. The next time they open up the app, it automatically sets the user interface to show the last item. In this case, it would be overkill for me to store this type of data in Core Data or other complex mechanism. I simply check NSUserDefaults for a value and go from there. It is important to remember that NSUserDefaults are just that, helpful for reading/writing user preferences and other similar things.

 

Saving data

Before we read or write data from NSUserDefaults, we must first get a reference to the NSUserDefaults class.

let prefs = NSUserDefaults.standardUserDefaults()

Once we have the reference saved to a constant, we can write data to it. You will be defining both the value and the key name to store the data.

prefs.setValue("Berlin", forKey: "userCity")
//This code saves the value "Berlin" to a key named "userCity".

 

Reading data

Reading data is similar to writing it. Again, let’s get a reference to the NSUserDefaults class and then we can query a key for a value.

let prefs = NSUserDefaults.standardUserDefaults()

Once we have the reference saved to a constant, we can read data from it.

if let city = prefs.stringForKey("userCity"){
   println("The user has a city defined: " + city)       
}else{         
   //Nothing stored in NSUserDefaults yet. Set a value.
   prefs.setValue("Berlin", forKey: "userCity")          
}

We are querying (in this case) the key named “userCity” for a value. If the key returns a value, we print it out to the console. Otherwise, if there is no value saved yet, we use .setValue to save the city to NSUserDefaults.

In this case we are saving a string but you can use this with any of the data types described above. If you need to persist when the app was last opened, you can use NSDate in combination with NSUserDefaults.

 

Synchronizing

Other than the Swift syntax, NSUserDefaults hasn’t really changed. You should note that in previous versions of iOS/OSX, writing data to NSUserDefaults wasn’t always immediate. Rather, it took a few seconds for the changes to persist. This was unfortunate when you were trying to persist data as the user closed the app or doing other important task.

A quick call to synchronize was all that was needed to ensure data was written immediately to NSUserDefaults. It seems that in Yosemite/iOS 8, this call to synchronize is no longer necessary. If you are coming from Objective-C, this may be a difficult habit to break. Apple recommends that we stop calling synchronize as it’s just slowing our apps down.

Old school:

[prefs synchronize]; //Objective-C
prefs.synchronize() //Swift

 

Other Notes

Don’t store sensitive data.  Data stored here is in plaintext (obviously) and can easily be read by anyone with half a brain and an iTunes cable. If you need to persist usernames, passwords or any other sensitive data, you should be using Keychain. Seriously, don’t store sensitive data in NSUserDefaults.

Don’t store large files. Technically, you can do it, but it’s not efficient. Because NSUserDefaults stores data as a property list file, the entire file is read/written out when you access it. If the file/data barely changes, you may be wasting resources accessing it this way. There is a place and mechanism for everything. Use NSUserDefaults for small bits of information and if you haven’t already, invest some of your time into learning Core Data for the larger, more complex data.

Note: (Swift) Strings, Arrays and Dictionaries are automatically converted to their NS-counterparts when saving to NSUserDefaults. You can also save Int, Float, Double & Bool to NSNumber as these are automatically bridged when using NSUserDefaults.