About the User Defaults System
The user defaults system manages the storage of preferences for each user. Most preferences are stored persistently and therefore do not change between subsequent launch cycles of your app. Apps use preferences to track user-initiated and program-initiated configuration changes.
What Makes a Good Preference?
When defining your app’s preferences, it is better to use simple values and data types whenever possible. The preferences system is built around property-list data types such as strings, numbers, and dates. Although you can use an
NSData object to store arbitrary objects in preferences, doing so is not recommended in most cases.
Storing objects persistently means that your app has to decode that object at some point. In the case of preferences, a stored object means decoding the object every time you access the preference. It also means that a newer version of your app has to ensure that it is able to decode objects created and written to disk using an earlier version of your app, which is potentially error prone.
A better approach for preferences is to store simple strings and values and use them to create the objects your app needs. Storing simple values means that your app can always access the value. The only thing that changes from release to release is the interpretation of the simple value and the objects your app creates in response.
Providing a Preference Interface
For user-facing preferences, Table 1-1 lists the options for displaying those preferences to the user. As you can see from this table, most options involve the creation of a custom user interface for managing and presenting preferences. If you are creating an iOS app, you can use a Settings bundle to present preferences, but you should do so only for settings the user changes infrequently.
Frequently changed preferences
Infrequently changed preferences
Preferences in Mac apps should be accessible from a Preferences menu item in the app menu. Cocoa apps created using the Xcode templates provide such a menu item for you automatically. It is your responsibility to present an appropriate user interface when the user chooses this menu item. You can provide that user interface by defining an action method in your app delegate that displays a custom preferences window and connecting that action method to the menu item in Interface Builder.
There is no standard way to display custom preferences from inside an iOS app. You can integrate preferences in many ways, including using a separate tab in a tab-bar interface or using a custom button from one of your app’s screens. Preferences should generally be presented using a distinct view controller so that changes in preferences can be recorded when that view controller is dismissed by the user.
The Organization of Preferences
Preferences are grouped into domains, each of which has a name and a specific usage. For example, there’s a domain for app-specific preferences and another for systemwide preferences that apply to all apps. All preferences are stored and accessed on a per-user basis. There is no support for sharing preferences between users.
Each preference has three components:
The domain in which it is stored
Its name (specified as an
Its value, which can be any property-list object (
The lifetime of a preference depends on which domain you store it in. Some domains store preferences persistently by writing them to the user’s defaults database. Such preferences continue to exist from one app launch to the next. Other domains store preferences in a more volatile way, preserving preference values only for the life of the corresponding user defaults object.
A search for the value of a given preference proceeds through the domains in an
NSUserDefaults object’s search list. Only domains in the search list are searched and they are searched in the order shown in Table 1-2, starting with the
NSArgumentDomain domain. A search ends when a preference with the specified name is found. If multiple domains contain the same preference, the value is taken from the domain nearest the beginning of the search list.
Application (Identified by the app’s identifier)
Languages (Identified by the language names)
The Argument Domain
The argument domain comprises values set from command- line arguments (if you started the app from the command line) and is identified by the
NSArgumentDomain constant. Values set from the command line are automatically placed into this domain by the system. To add a value to this domain, specify the preference name on the command line (preceded with a hyphen) and follow it with the corresponding value. For example, the following command launches Xcode and sets the value of its
IndexOnOpen preference to
localhost> Xcode.app/Contents/MacOS/Xcode -IndexOnOpen NO
Preferences set from the command line temporarily override the established values stored in the user’s defaults database. In the preceding example, setting the
IndexOnOpen preference to
NO prevents Xcode from indexing projects automatically, even if the preference is set to
YES in the user defaults database.
The Application Domain
The application domain contains app-specific preferences that are stored in the user defaults database of the current user. When you use the shared
NSUserDefaults object (or a
NSUserDefaultsController object in OS X) to write preferences, those preferences are automatically placed in this domain.
Because this domain is app-specific, the contents of the domain are tied to your app’s bundle identifier. The contents of this domain are stored in a file that is managed by the system. Currently, this file is located in the $HOME
/Library/Preferences/ directory, where $HOME is either the app’s home directory or the user’s home directory (depending on the platform and whether your app is in a sandbox). The name of the user defaults database file is <ApplicationBundleIdentifer>
.plist, where <ApplicationBundleIdentifer> is your app’s bundle identifier. You should not modify this file directly but can inspect it during debugging to make sure preference values are being written by your app.
The Global Domain
The global domain contains preferences that are applicable to all apps and is identified by the
NSGlobalDomain constant. This domain is typically used by system frameworks to store system-wide values and should not be used by your app to store app-specific values. If you want to change the value of a preference in the global domain, write that same preference to the application domain with the new value.
Examples of how the system frameworks use this domain:
Instances of the
NSRuleViewclass store the user’s preferred measurement units in the
AppleMeasurementUnitskey. Using this storage location causes ruler views in all apps to use the same units.
The system uses the
AppleLanguageskey to store the user’s preferred languages as an array of strings. For example, a user could specify English as the preferred language, followed by Spanish, French, German, Italian, and Swedish.
The Languages Domains
For each language in the
AppleLanguages preference, the system records language-specific preference values in a domain whose name is based on the language name. Each language-specific domain contains preferences for the corresponding locale. Many classes in the Foundation framework (such as the
NSScanner classes) use this locale information to modify their behavior. For example, when you request a string representation of an
NSCalendarDate object, the
NSCalendarDate object uses the locale information to find the names of months and the days of the week for the user’s preferred language.
The Registration Domain
The registration domain defines the set of default values to use if a given preference is not set explicitly in one of the other domains. At launch time, an app can call the
registerDefaults: method of
NSUserDefaults to specify a default set of values for important preferences. When an app launches for the first time, most preferences have no values, so retrieving them would yield undefined results. Registering a set of default values ensures that your app always has a known good set of values to operate on.
The contents of the registration domain can be set only by using the
Viewing Preferences Using the Defaults Tool
In OS X, the
defaults command-line tool provides a way for you to examine the contents of the user defaults database. During app development, you might use this tool to validate the preferences your app is writing to disk. To do that, you would use a command of the following form from the Terminal app:
defaults read <application-bundle-identifier>
To read the contents of the global domain, you would use the following command:
defaults read NSGlobalDomain
For more information about using the defaults tool to read and write preference values, see
defaults man page.