UserDefaults

UserDefaults is essentially a very tiny light weight database that persists between launchings of the app. It's great for things like "settings" and such, not for anything big.

We are limited in what we can store in UserDefaults, it only stores Property List data.

A Property List is any combo of Array, Dictionary, String, Date, Data or a number (Int, etc). This is an old objective-c api with no type that represents all those, so the api uses Any. If this were a new, swift-like api, it would almost certainly not use Any (likely there would be a protocol or some such that those types would implement.)

It's "core" functionality is simple. It just stores an retrieves Property List by key...

func set(Any?, forKey: String)  
func object(forKey: String) -> Any? // optional because it might not be found  

It say Any but it's not really Any it must be one of the types mentioned above, and when it returns a property it is guaranteed to be a Property List.

Reading And Writing

We don't usually create one of these databases with UserDefaults(). Instead, we use the static (type) var called standard.

let defaults = UserDefaults.standard  

Setting a value in the database is done with set. You can pass anything as the first argument as long as it's a combo of the Property List types.

defaults.set(3.1415, forKey: "pi")  
defaults.set([1,2,3], forKey: "My Array")  
defaults.set(nil, forKey: "Some Setting") // removes any data at that key  

Getting defaults outs with UserDefaults has come convenience methods so that we don't get a value of type Any? but rather they type we are looking for, but when we do get type Any of course it will be a Property List type.

func double(forKey: String) -> Double  
func array(forKey: String) -> [Any]? // retunrns nil if non-Array at that key  
func dictionary(forKey: String) -> [String: Any]? // note that keys in return are Strings  

Saving

Our changes will occasionally be auto saved, but we can force them to be saved at any time with synchronize. It's not computationally "free" to synchronize, but it's not that expansive either.

if !defaults.synchronize() {  
  // failed! but not clear what you can do about it
}