|
Technote 1134The Preferences Problem |
CONTENTSThe Preferences
Problem |
Preferences: nearly every application has them, but there is no Mac OS API specifically designed to help you deal with them. This requires you to write a fair amount of code to deal correctly with preferences. This Technote will attempt to outline the problems with preferences files and the solutions to those problems so that you can code a robust solution. Often a problem has multiple solutions, and none of them is the obvious best-choice solution for all possible cases. This Note lists the top options, and discusses each solution so that you can make an informed decision about which to implement. This Note is directed at developers who have a preferences file, or files, and who want to make sure that they are working correctly with those files by making sure they are covering all reasonable possibilities. |
The Preferences ProblemPreferences files: nearly every application of substance has them, but they are often the cause of great pain and frustration when they should make your life simpler. What are the major problems relating to preference files?
In the real world it is impossible to solve all of these problems with one solution that will always be the correct one. With that in mind, we will attempt to give you the information that you need to come as close as possible to an ideal solution for your application. Issue 18 of develop Magazine included an article called "The Write Way to Implement Preferences Files." DTS does not believe you should follow the recommendations in that article. This Technote supersedes that article. If, for historical interest, you wish to see what it is we are recommending you avoid, you can download the article. |
DiscussionHow you store your preferences inside a file is up to you. You can store your preferences as a flattened structure that your application will read directly into a handle when it starts, or you can store it in a much more complicated form. What should I name my preferences file(s)?The name of your preferences file is completely up to you. The only suggestion that DTS has is that it not end with "Prefs": use "Preferences" instead. This way the user has a clear idea that the file contains SurfWriter preferences and not some mysteriously essential data which might be dangerous to delete. This seems like a trivial point, but unless your
application's name is so long that "Preferences" can't be
tacked onto the end of it, you should avoid the contraction.
You only have to type it once (presumably into a
Where do preferences file(s) go?The easy answer is that you should put them in a file or
files in the Preferences folder, as identified by a call to
If you have only one preferences file, you should put
that file into the Preferences folder (returned from
When your application needs more than one preferences file, consider creating a folder within the Preferences folder and putting your preferences files in this additional folder. However, storing everything in the Preferences folder hierarchy is not best for all applications. For example, in a multiple-user situation, you may want to have a preferences file stored in each user's personal folder rather than have a large number of files kept in the Preferences folder. Another option that some programs already implement is the concept of "local preferences". A local preference is one that is stored in the same folder as the application. The application first looks for a local preferences file, and if it does not find a local one, it then looks for a preferences file in the Preferences folder. This add complexity to the preferences search code, but for that added complexity your users gain the ability to easily:
What file type and creator should I use for my preferences file(s)?What file type?You should give your preferences file the type
Finder Preferences This might be confusing for the user, since nearly every
preferences file has a type of If you have files other than preferences files that you
are storing in the Preferences folder (or a folder in the
Preferences folder), feel free to use any type that you
wish. For instance, if you have a log file in the
Preferences folder, it is perfectly reasonable to make it of
type In summary, if it's a preferences file, it should have a
type of What creator code?There are three schools of thought on this issue. The
first claims you should give your preferences file a creator
code that matches your application signature. The second
claims that you should give it a creator of
Using your application's creator codeThere are good reasons why you would want to give your preference file the same creator as your application signature. They are (in no particular order):
However, there is also a reason why you would not want to use your application signature as the creator code of your preferences file:
Using a creator code of
|
Note: There is code at the end of this Note that shows how you might want to locate a preferences file by creator code and/or file name. You may find this a good start for your own search code. |
There is the possibility that the user of your application will use a preferences file that was not created with the same language code as the currently running system. For instance, a U.S. user may have sent their preferences to a Japanese colleague.
If your application finds its preferences based on a creator code and not a name, then this combination of Japanese application and U.S.-named preferences file will work as the user expected. If your application always opens the preferences file by name, or requires that the name be a specific string, then you prevent the easy duplication of preferences files, and make it difficult for users to make copies of their preferences files for rapid switching between different preference sets.
The application-missing message string is a 'STR
'
resource ID -16397 put in a file by the creating
application, which the Finder uses to tell the user why a
file could not be opened. The message should tell the user
which application created the file and the purpose of the
file. This string should be used if you give your
preferences file (or any other file) a creator code that is
not the same as your application signature. This way, when
the user attempts to open your preferences file they will
receive a message such as:
"This document describes user preferences for the application SurfWriter. You cannot open or print this document. To be effective, this document must be stored in the Preferences folder in the System Folder."
There is also a missing-application name string which is
a 'STR '
resource ID -16396. This resource is
simply the name of the application that created the file
("SurfWriter") which the Finder will use to tell the user
which application created a specific file when that
application cannot be found. Normally this string is used
only for documents that are meant to be opened by the
user.
Important: Do not use both the application-missing message string and the missing-application name string; use one or the other, but not both. For more information on application-missing messages, see Inside Macintosh: Macintosh Toolbox Essentials, Chapter 7 - Finder Interface, using the Finder Interface Displaying Messages When the Finder Can't Find Your Application. |
Finding your preferences file is simple if you find it by
name; it's either there or it isn't. If you find your
preferences file by creator code, you will have to search
the entire Preferences folder for a file of the correct
type. You may want to also match it by name in case multiple
files have the same creator code, which is especially likely
to happen if the creator code you use is
'????'
.
To search for files with a specific creator code, use
indexed calls to PBHGetFInfo
to have it return
you the Finder information about each file in a given
directory. Remember that after each call to
PBHGetFInfo
, you have to reset
ioDirID
field of the parameter block because
PBHGetFInfo
changes the value of this
field.
'vers'
resource in my preferences file(s)?Yes, you should. Every file that is part of your
application should have a 'vers'
resource ID 1
and 2 in it as a matter of course, and preferences files are
not an exception.
The immediate benefit of 'vers'
resources is
that a user will see a more complete Get Info dialog in the
Finder: one showing the application's name and version that
belongs to the file. A future benefit of the
'vers'
resource is that it can come in handy
when a new version of your program has to identify and
convert an older version's preferences settings to a new
format.
This is easy; if you give your preferences file a type of
'pref'
, it will automatically get the correct
icon (the default preferences file icon). You should not
have an entry of 'pref'
in your application's
bundle resource. Furthermore, having files with generic
icons makes opening the Preferences folder a lot faster.
We discourage developers from trying to have preferences files with non-generic (custom) icons. However, if you want a custom icon, use a custom Finder icon so that your preferences file will have an icon even if your application is deleted. This may help the user determine that they can now delete your preferences file. Another reason for using a Finder custom icon is that the Finder only has to open one file (the preferences file) whose location it knows, rather than searching the desktop database on every volume, including volumes like AppleShare volumes mounted over Apple Remote Access, which may be very slow.
For information on how to create a custom Finder icon, see Inside Macintosh: Macintosh Toolbox Essentials, Chapter 7 - Finder Interface, using the Finder Interface, Creating Customized Document Icons.
This is a problem only if you give your preferences file the same creator code as your application signature. There are several thoughts on what to do if your application is asked to open a preferences file:
'pref'
from your application's "open documents" Apple Event
handler).There are no real disadvantages to any of these methods other than the user experience that they offer, and only you are able to determine what user experience to deliver (since Apple has no official position on this subject).
This would seem to be an easy question to answer; however, there are two different opinions on this subject.
The opinions are:
The obvious advantage to the first approach is that if the user never changes the preferences from their default values, they never have a preferences file wasting space on their hard drive. This also makes it easy for someone to install your application, try it, and then delete it without having to search their system for orphaned files. This point is especially directed at developers whose software is distributed on a trial-use basis.
Always creating a preferences file makes for slightly simpler code, but since you have to be prepared to run even if you cannot create a preferences file, you might as well wait until you actually need to create a preferences file before dealing with those possible problems.
One of the problems of creating a preferences file is that you may not be able to create it because the volume or system folder is locked. For ideas of what to do in this situation, see the following section on what to do if the file is on a locked volume or the preferences file is locked.
There is also the problem of what to do if another file or folder exists where you would want to save your preferences file or folder. For ideas when in this situation, see the section on what to do if your preferences file is usurped by another application.
If your application is not able to save or update a preferences file, what do you do?
However, what if the user wants to use your program with new preferences?
Many applications have preferences files that are merely a resource fork that contains one or more custom resource data structures that the program reads in during its launch. If you have a preferences file based on the Resource Manager, you are subject to its limitations and you should be aware of them. One of the most important things to know when relying on the Resource Manager is that the current Resource Manager doesn't perform the most robust sanity checking before opening a resource file. If your resource file has become corrupted in such a way as to cause the Resource Manager to crash or produce an error, the user will not have any way of discovering the problem. Deleting the offending preferences file may be one of the last things that they try.
For this reason, you may want to perform sanity checking on the resource map of your preferences file before you attempt to open it through the Resource Manager. Code for this is provided in the public domain as part of Internet Config; look for the file called "ICResourceForkSanity.c" in the IC Programmers Kit.
If your preferences file is corrupted, you should alert the user to that fact, and you should not take any immediate action that isn't easily reversible. It may be that your preferences have been usurped by another application and merely appear to be corrupt from the perspective of your application. In that case, you don't want to delete the file. Allow the user to have the final decision as to what action should be taken to correct the problem, though you are free to suggest the course of action you believe to the be the best.
If your preferences file has not been usurped and is indeed corrupt, you should attempt to continue running, either with default settings, or with backed-up settings. Forcing the user to quit and delete your preferences file is frustrating for the user. Your application may be perfectly usable with the default settings, and the user may not want to spend the time fixing the problem immediately if they are in a hurry to perform a simple task.
As an example of a good thing to do, Internet Config makes a copy of its preferences file's resource fork and stores it in the data fork of the preferences file. If the resource fork turns out to be corrupt, it deletes the resource fork, copies the saved preferences from the data into the resource fork, and continues. This is a complicated solution and it doubles the size of your preferences file, but usually that is not a significant amount of disk space.
If you would like to attempt such a solution in your application, the code for Internet Config is in the public domain; you are free to use it in your application.
If another file or folder exists where you would want to put your preferences, you should alert the user to this fact, but you should also be able to continue gracefully.
If possible, attempt to save your preferences file in some alternate location. If there is a permanent conflict, the user doesn't have to choose between your application and some other application, or use one of the applications without their preferred preferences.
One of the easiest workarounds to this problem is to locate your preferences file by a unique creator code (your application's signature springs to mind), which allows the user to rename your preferences file and not affect your application at all.
If you choose to locate your preferences file by name, putting a registered string (such as "Apple") in it may help to reduce the likelihood that it will conflict.
Overwhelmed?If you are overwhelmed by all these choices, DTS prefers that:
|
SummaryMaintaining a preferences file isn't as simple as it seems at first glance. There are options to consider and trade-offs to be weighed, but because nearly every application must have a preferences file, correct maintenance is vitally important. In this Note, you have learned of all the possibilities we could think of and been shown their merits and flaws. Now it is up to you to decide what is right for you and your users. |
Change History
To contact us, please use the Contact
Us page. |