What is UserDefaults, what can it store, and why do its typed getters mislead?

2.5.7 · L1 · Interview

Predict first

What does this print for a key that was never set?

let d = UserDefaults(suiteName: "demo")!
print(d.integer(forKey: "nope"), d.object(forKey: "nope") as Any, d.bool(forKey: "nope"))
  • 0 nil false
  • nil nil nil
  • 0 0 false

Predict first

What does this print?

let d = UserDefaults(suiteName: "demo2")!
d.set("42", forKey: "n")
print(d.integer(forKey: "n"))
  • 0
  • 42
  • Crash

Predict first

What happens?

struct Settings { var dark = true }
let d = UserDefaults(suiteName: "demo3")!
d.set(Settings(), forKey: "s")
print("saved")
  • Prints saved
  • Crashes

Mental model. UserDefaults is the sticky-note wall by your door: perfect for “dark mode on”, hopeless for a photo album.

UserDefaults is a small persistent key-value store, saved as a property list in the app’s Preferences. It stores only property-list types: String, Number, Bool, Date, Data, and arrays or dictionaries of those. Storing anything else, such as a custom struct, throws an Objective-C exception and crashes. Encode it to Data first.

The typed getters hide a trap: integer(forKey:), bool(forKey:) and friends return 0 or false for a missing key, so you cannot tell “never set” from “set to zero”. Use object(forKey:) and check for nil, or register(defaults:) to define a fallback. The getters also coerce: a stored string "42" reads as 42.

The typed getters invent 0 and false; only object(forKey:) shows that nothing is there.

integer(forKey:) converts a stored numeric string, so a type mix-up goes unnoticed.

A struct is not a property-list type. Encode it to Data (JSON or plist) before storing.

Common traps

  • Saving a custom type. Crashes with “attempt to insert non-property list object”.
  • Reading a missing bool as the user’s choice. false may only mean “never set”.

They might follow up with

  • Is writing instant? Reads see it immediately; the disk write is batched. synchronize() is no longer needed.
  • How do you share settings with an extension? UserDefaults(suiteName:) with an App Group identifier.

Related questions

  • 2.5.8 What belongs in UserDefaults, and how do you design and test around it?
  • 2.5.6 What is a property list, and where do you meet one?

← What is a property list, and where do you meet one?   What belongs in UserDefaults, and how do you design and test around… →