あまつぶ

9.9【初期設定はXMLで】

 前回掲載したソース、WindowsのIE5でフォントの設定を細小にして見ると字がつぶれてまったく読めなかった。一応対処してみたつもりだけど、どうだろう。

 CD-ROMのイジェクト。MacOS Xでは、F12を押すとすぐに出てくるらしい。deleteを押すつもりがちょっとずれて、びっくりした。

 WebColorXの続き。1.0b2では、Nib対応、Preference Services対応に挑戦。機能では、初期設定ダイアログの追加して、ホットキーやコピーするタグの種類を変更できるようにしてみた。Nib対応はひとまず置くとして、今回はPreference Servicesのことを書いてみようと思う。
 Xには、初期設定をXML形式の「〜.plist」というファイルに保存するための機能がある。これをになうのがPreference Servicesだ。これまでは、初期設定ファイルはシステムフォルダの「初期設定」フォルダにリソースファイルとして保存するのが一般的だったが、Xでは、~/Library/PreferencesにXMLファイルとして保存するのが一般的なようだ。もちろん、リソースファイルで管理することも可能だが、Preference Servicesを使うと、リソースファイルを開いたり閉じたりということをする必要がなく、また、Developer Toolsに付属するPropertyListEditorで簡単に編集することが可能になるのだ。既存のものを移行するとなるとなかなか大変だが、新規のものならば楽できる部分もありそうだ。
 Preference Servicesを使うと、例えば、

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
<plist version="0.9">
<dict>
  <key>Hot key</key>
  <dict>
    <key>Key code</key>
    <integer>25</integer>
    <key>Modifiers : command key</key>
    <true/>
    <key>Modifiers : control key</key>
    <false/>
    <key>Modifiers : option key</key>
    <false/>
    <key>Modifiers : shift key</key>
    <true/>
  </dict>
  <key>Last used color</key>
  <dict>
    <key>Blue</key>
    <integer>13107</integer>
    <key>Green</key>
    <integer>52428</integer>
    <key>Red</key>
    <integer>65535</integer>
  </dict>
  <key>Tag type</key>
  <integer>3</integer>
  <key>Tag use capitals</key>
  <false/>
</dict>
</plist>


こんな初期設定ファイルが作られる。XMLについては詳しく触れないが、要はHTMLと同じようなマークアップ言語で、文字列を<...>から</...>で囲んでなんらかの属性(意味)をあらわすもの。例えば、7行目の「<key>Key code</key>」の部分は「Key code」という名前のキーをあらわし、その次の「<integer>25</integer>」は25という数値をあらわしている。
 plistでは、基本的に、キーとそれに対応する値を交互に書き表わす。値には、数値や文字列はもちろん、Dictionaryという複数の数値や文字列を組み合わせたもの(Cでいうところの構造体のようなものだと思えばわかりやすいだろうか)が使用できる。上の例では、数値、Dictionaryと、ブール値(<true/>あるいは<false/>)が使われている。同じ型のデータがいくつか続く場合には、配列(Array)を使うこともできる。

 Preference ServicesのAPIは、CFPreferences.hに書かれているのだが、キーと値を指定してデータをやり取りするだけの簡単なものしか存在しない。Dictionaryや数値を扱うためのものは、それぞれCFDictionary.hやCFNumber.hにわかれて存在しているのだ。
 さて、まずは、初期設定ファイルにデータを保存する方法から。Preference Servicesには、ユーザ間で共通の設定などをサポートする機能もあるが、ここでは簡単に、ユーザやホストごとに異なる設定を作ることにする(したがって、~/Library/Preferencesに保存される)。上記CFPreferences.hに、CFPreferencesSetAppValue()というAPIがある。第1パラメータにはキーの名前、第2パラメータには設定する値(数値、文字列など)を指定し、第3パラメータは初期設定ファイルの名前に相当するものだが、通常はkCFPreferencesCurrentApplicationを指定すればいいだろう。
 キーの名前は、おそらく固定値を使うだろうから、上の例のKey codeキーでは、CFSTR("Key code")と指定するだけでよい。CFSTRは、C文字列の定数をUnicodeに変換するためのもので、CFString.hで定義されている。ま、あまり細かいことは気にせずに、文字列の定数を使う時はこうだって覚えておけばよさそうだけど。
 値は、指定するものによってやり方が異なる。例えば、数値なら、CFNumberCreate()(CFNumber.hで定義)でCFNumberRef型のデータを作るし、Dictionaryなら、CFDictionaryCreateMutable()で作成しておいて、CFDictionarySetValue()で値を追加していく。Last used colorキーから後ろの部分について保存すると、

/* last used color */
dict = CFDictionaryCreateMutable(kCFAllocatorDefault,0,
    &kCFTypeDictionaryKeyCallBacks,&kCFTypeDictionaryValueCallBacks);

temp =
gPrefs.lastUsedColor.red;
num = CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt32Type,&temp);
CFDictionarySetValue(dict,CFSTR(
"Red"),num);
CFRelease(num);

temp =
gPrefs.lastUsedColor.green;
num = CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt32Type,&temp);
CFDictionarySetValue(dict,CFSTR(
"Green"),num);
CFRelease(num);

temp =
gPrefs.lastUsedColor.blue;
num = CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt32Type,&temp);
CFDictionarySetValue(dict,CFSTR(
"Blue"),num);
CFRelease(num);

/* 保存 */
CFPreferencesSetAppValue(CFSTR(
"Last used color"),dict,
    kCFPreferencesCurrentApplication);
CFRelease(dict);

/* tag type */
num = CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt16Type,&
gPrefs.tagKind);
CFPreferencesSetAppValue(CFSTR(
"Tag type"),num,
    kCFPreferencesCurrentApplication);
CFRelease(num);

/* tag use capitals */
CFPreferencesSetAppValue(CFSTR(
"Tag use capitals"),
    (
gPrefs.tagCapital ? kCFBooleanTrue : kCFBooleanFalse),
    kCFPreferencesCurrentApplication);

CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);


こんなふうになる。最後に使っているCFPreferencesAppSynchronize()で、ファイルに書き込まれる。アプリケーションの終了時ならば気にすることはないと思うけど、途中で保存しておきたい場合は呼んでおくこと。また、CFNumberCreateで作ったCFNumberRef、CFDictionaryCreateMutableで作ったCFDictionaryRefはCFRelease()で解放すること。ブール値の場合は、定数が用意されているのでこれを使うようだ。

 長くなったので今回はここまで。次回は、読み込みルーチンの予定。

August 26, 2001 ↑ September index → September 10, 2001