Some of the most common Mac problems involve, and are solved by, preference files for macOS features and apps. They’re also some of the most mystifying, as it’s so easy to ‘fix’ something only to find it undone again in a few moments. A week ago, I looked here at global defaults, which control features such as App Nap and human interface elements. Before going on to look separately at the long list of settings controlled by preference files, this article considers how those preferences are managed, set, and coded.
Before OS X 10.9 Mavericks, simple techniques for working with preference files generally worked fine. If you wanted to fix or change settings in a preference file affecting something which was already active, you could usually edit the Property List containing that setting, then log out and back in again, or restart. But for most apps, as long as the app wasn’t running at the time that you changed its preferences, it worked fine. Try this now, and results are completely unpredictable, and likely to fail.
The reason is that Mavericks changed the way that preference files work. Even when you open a preference file for an app which isn’t currently running, what you see in Mojave may well not be the preferences which the app will use when it is run next. In short, what you see is usually not what you get.
From 10.9 onwards, macOS runs an extra service,
cfprefsd, which is responsible for managing the great majority of preference settings across macOS and almost all third-party software. Look in Activity Monitor, and you’ll see at least two instances of
cfprefsd running at any time: one serving preferences for processes which are owned by root, and one for each user of your Mac, even when they’re not logged in. You may also see another instance owned by
The first time that you run an app or a preference pane, or anything else which uses preference files stored in ~/Library/Preferences or /Library/Preferences, after logging in,
cfprefsd reads in its preference file(s) from storage in that folder. It then makes those settings persist, even over many days, until you log out, shut down, or restart.
If you change those settings using the app, or another app or tool which changes them using official mechanisms, those changes are reflected in the copy kept by
cfprefsd, and written out to storage, updating the preference file within a second or two. This usually happens using a ‘safe save’ strategy, in which the new file is written out with a dummy extension, and then replaces the original.
But once it has been run in the current session, the app will not normally read its preference file again until after you log back in and start it again. So if you try editing the preference file, move it, or remove it, even though the app isn’t running at the time, those changes are almost certain to be ignored.
There are ways in which you can force an updated preference file to be read again by
cfprefsd, or for the preferences to be reset to defaults. In rough order of preference, these are:
- use Thomas Tempelmann’s free Prefs Editor, or another third-party utility, or the command tool
defaults, to update the ‘real’ preference file rather than editing it;
- delete the preference file using
defaults, and force the app to create a new, default set of preferences;
- edit the preference file manually or remove it, log off, and log back in again;
- edit the preference file manually or remove it, and restart;
- edit the preference file manually or remove it, kill
cfprefsdand allow the system to restart it.
The first two are preferable by a long way, as the last three are prone to failure and causing weird behaviour.
If you’re happy to use Terminal’s command line, the
defaults command provides a reliable way of changing preference settings, whether or not they are being managed by
cfprefsd at the time. If you’re not comfortable in Terminal, don’t mess around, just use Prefs Editor instead.
To delete an existing preference file, quit the app or pane which uses it, and enter the command
defaults delete ~/Library/Preferences/filename
filename is the name of the preference file to be deleted, including the .plist extension, e.g.
com.appvendor.appname.plist. If you need to do this for a preference stored in /Library/Preferences, you will probably have to preface the command with
sudo to obtain the necessary elevated privileges.
What will normally happen then is the preference file will not be deleted, but left empty of all keys and settings, and
cfprefsd will remove any persistent settings for that file. The next time that app runs, it will create a default set of preferences, which will be written out to its preference file. When you set its preferences, those will be updated in that preference file.
You can view the contents of a given preference file using the command
defaults read domain
domain is the app ID, e.g.
com.appvendor.appname; in this case, drop the .plist extension.
You can write a new value for a given key in a given preference file using the command
defaults write domain key 'value'
domain is the app ID,
key is the name of the key in the Property List file (wisely set in “” to cater for spaces, for example), and
value (which must be in single quotes ”) is the value to set it to. This is straightforward when dealing with a number or string, but gets more tricky when working with arrays and dictionaries – for which you will almost certainly want to use Prefs Editor instead.
You can also use the
defaults read domain command to get an app to read in a modified preference file.
To work with settings in the global domain, use the -g option instead of specifying a domain, e.g.
defaults read -g AppleTemperatureUnit
You can reset or change the preference settings of an app, provided that it is not running at the time, and is not set to run at login.
Although in theory you should be able to edit, replace, or remove the preference file and then log out and log in, that is usually unreliable, and
cfprefsd will try to spoil your day. A better plan is to move the current preference file outside the Library/Preferences folder, preferably well away in Documents or similar. If you intend editing it by hand, do so now. Then log out and back in. If you want to use your modified preference file, move that back to the correct Preferences folder before that app starts up again.
The way that preference files are handled may seem bad for users, but it can be a nightmare for a developer. Once a preference file contains a value which causes an app under development to crash, for instance, it can be very tricky to get the app back running again, as the crashing app is unlikely to be able to write out a corrected preference file.
If your app under development is having problems reading its preference file, hand-editing that preference file will do no good, unless you log out and back in again to force the preference file to be read again.
There are three useful ways to tackle this. One is to comment out all code which reads preference settings, ensure that the code to write preferences is robust and correct, then to get that temporary version of the app to write a fresh preference file. You can also perform surgery on your app’s preference file using Prefs Editor (which every developer should keep to hand, anyway), or use the
defaults tool if you prefer the command line.
Currently, documentation of UserDefaults (NSUserDefaults for Objective-C) offers the
synchronize() function, which used to purport to write any change to storage, and to update “all unmodified persistent domains to what is on disk”. Apple doesn’t appear to have formally deprecated it, instead damning it by stating “this method is unnecessary and shouldn’t be used.” In contrast, if you use CFPreference calls instead, you’ll need to use its equivalent method
CFPreferencesAppSynchronize(_:), which is required to write changes to permanent storage.
Developing modified preference support can be extremely frustrating in Xcode, which lacks any intrinsic ability to change or trash existing preference settings. If you don’t understand how settings persist, that can be profoundly confusing. This is particularly true as the behaviour of preferences remains largely undocumented by Apple, or at least not documented in any obvious way.
If you want to circumvent all this hassle, don’t use UserDefaults (NSUserDefaults) or any of the CFPreferences calls, but treat your preference file as a normal Property List. You’ll end up having to write a lot of your own code, then, of course.