Preferences

From iPhone Development Wiki
This article is about reading and writing preferences. For the Preferences user interface framework, see Preferences.framework.

Tweaks typically have preferences that can be set by the user from the Settings app. The Preferences framework uses the CFPreferences family of functions to read and write preferences. Before OS X 10.8 and iOS 8, these functions would directly read and write a plist with the name of the application identifier in ~/Library/Preferences. (Note that when an app is sandboxed in a container, the home directory is the path to the container, not the user's home directory.) Nowadays, preferences are managed by a daemon called cfprefsd.

The Foundation class NSUserDefaults provides a subset of features over the CFPreferences functions. It appears to be intended more as a simple-to-use class that handles calling CFPreferences functions for you, as opposed to being feature-by-feature compatible with CFPreferences.

CFPreferences functions can take and return CFStringRefs and CFPropertyListRefs. As such, you can toll-free bridge these from or to their matching Foundation classes.

cfprefsd

cfprefsd is the daemon that handles reading and writing preference values. It also caches values in memory so that they can be returned faster. Its goal is to avoid disk reads/writes as much as is possible. This has caused some confusion among tweak developers who have for the most part simply been reading their preference plist directly from the disk, which isn't written to until cfprefsd decides to flush its in-memory cache, or it's sent a SIGTERM (killall cfprefsd). It was introduced to OS X with 10.8, and to iOS with 8.0.

Due to cfprefsd not working as desired in processes that live in an app container and having no documentation other than a vague man page, various developers have created different solutions to read and write preference values. These are outlined at PreferenceBundles § Loading Preferences.

The signal SIGUSR1 can be sent to cfprefsd to make it write a file to /tmp. It provides data about each preference domain read or written to using CFPreferences APIs since the daemon started, in the following form:

$ killall -USR1 cfprefsd
$ head -24 '/tmp/cfprefsddump(166:460692319.078117).txt'

*****************************************************
Domain: fud
User: root
Container: (null)
Path: /Library/Managed Preferences/root/fud.plist
plist data:(null)
shmem index:2017
dirty:0
byHost:1
mode:600
isMultiProcess:1

*****************************************************
Domain: com.apple.WebKit.Networking
User: mobile
Container: (null)
Path: /var/mobile/Library/Preferences/com.apple.WebKit.Networking.plist
plist data:(null)
shmem index:1145
dirty:0
byHost:0
mode:600
isMultiProcess:1

Examples

To do: read this carefully and move all information regarding preferences to a more appropriate place. Bring the following contents:

Tweak part

As opposed to using NSDictionaries and [NSHomeDirectory() stringByAppendingFormat:@"/Library/Preferences/%s.plist", "com.your.tweak"], the following implementation uses NSUserDefaults, which works properly for unsandboxed processes, so read the previous links to handle preferences on sandboxed processes until an implementation is added here.

Preference plist

Choose any of the following styles, see preferences specifier plist for all available specifier types and how to use them.

Reduced style

Provides a switch on the root section of the preferences (like Airplane Mode). Recommended for configuration-less tweaks.

Saved in your tweak's folder as layout/Library/PreferenceLoader/Preferences/com.your.tweak/entry.plist

entry.plist

Extended Style

Provides a pane where other cells can appear (like Wi-Fi). Recommended for configuration-friendly tweaks.

Saved in your tweak's folder as layout/Library/PreferenceLoader/Preferences/com.your.tweak/entry.plist

entry.plist

Inside PreferenceBundles

Provides a static list of cells. Recommended for Preference Bundles of tweaks.

Saved in your tweak's Preference Bundle subproject folder as Resources/com.your.tweak.plist

com.your.tweak.plist

Flipswitches

After using the Flipswitch NIC template, modify accordingly