![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ||
![]() | ![]() | ![]() | ![]() | ![]() |
|
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
以下は、Mac OS X 10.4.11 上の Xcode 2.5 で説明しています。
| 1 実行 2 ファイル構成 3 PreferencesExample.c 3.1 main 関数 |
3.2 show 関数 関数3.3 simplePreferencesExample 関数4 まとめ |
まず、Xcode 上でビルドして実行してみます。Xcode の実行ログは以下のようになります。
翻訳すると、次のようなメッセージが出力されています。
さて、もう一度実行してみます。すると今度は次のようなメッセージが出ます。
このサンプルは、環境設定に格納したハイスコアの数値をとりだし、毎回 5 ずつ増やしていることがわかります。ここで、現在のユーザーフォルダ内の「ライブラリ」>「Preferences」を見てみましょう。「A Game.plist」という名前のファイルがあります。プロパティリストエディタで開くと、「High Score」というキーと、数値 10 が格納されているのがわかります。
プロジェクトを構成しているファイルは、PreferencesExample.c だけです。あとは External Frameworks and Libraries 内で Core Foundation フレームワークに対してリンクされていることに注意してください。
main 関数まず、main 関数を見てみます。PreferencesExample.c では以下のようになっています。
コマンド行からの引数は一切利用せず、引数なしの 1つの関数を呼び出しているだけです。これらの関数を見ていきます。
show 関数その前に、サンプルでログ出力をするため、共通に定義されている関数があります。それは show です。この関数は、CFString オブジェクトである書式文字列と、可変個の書式変数の値を渡すことで、結果を printf で出力してくれます。
まず、可変個引数の受けとり用のリストを作成します。ここでは行っていませんが、このリストから type va_arg(va_list ap, type); で引数をとりだすことができます。type とあるように、あらかじめ型がわかっている必要があります。このリストを使って、CFStringCreateWithFormatAndArguments 関数で、resultString に結果の文字列を作成しています。この関数の引数は、最初がアロケーター(NULL はデフォルト)、次は書式指定のオプション(現在は無効なのでつねに NULL)、その次が書式文字列の CFString で、最後が va_list 型になっています。アロケーターがデフォルトになっていることに注意してください。これにより、この割り当ては、サンプルのアロケーターを経由しません。
次に、CFStringCreateExternalRepresentation で printf に渡すための文字列データが入れられた CFData を作っています。最後の '?' は変換できない文字をどういう文字として表すかを指定するものです。このデータ作成が成功したら、次に printf に渡します。「%.*s\n\n」という書式文字列で、%s はヌル終端の文字列を渡すことを指定し、その前の精度指定「.*」は、最大文字数を表し、ここでは * で引数として渡すことを指定しています。そのため、文字列後の引数は、データのバイト長、データという順番で渡されています。あとは割り当てたデータを解放しています。
この関数に渡す書式文字列は、たいてい CFSTR マクロでコード中に直接書かれます。このマクロは、定数文字列から CFString を作ります。ただし、7 ビット ASCII(127 までのコード)しかサポートしてないことに注意してください。日本語を使うなら、別の方法が必要です。
simplePreferencesExample 関数simplePreferencesExample は、以下のようになっています。この関数は、『Core Foundation のための環境設定プログラミングトピック』>「単純な環境設定の更新」で紹介されているコード例とほとんど同じです。コメント量などが違うので、訳して、説明も追加します。
構造自体は非常に簡単なのでわかりやすいと思います。まず最初に以前の値を、1 で、CFPreferencesCopyAppValue で取得しています。ここで引数は、キーの名前の CFString オブジェクト、そしてアプリケーション ID です。highScoreKey、appName は関数の先頭にあります。
このサンプルでは、appName として定数文字列を設定していますが、通常は、kCFPreferencesCurrentApplication 定数を渡せば、現在のアプリケーションに対する環境設定になります。それに変えてビルドしてみます。古いハイスコアがないことを示すメッセージが出たことでしょう。環境設定フォルダ内を見てみると、「A Game.plist」とは別に「PreferencesExample.plist」というファイルができているのがわかります。バンドル形式の info.plist をもつアプリケーションでは、通常、アプリケーションの識別子が使われます。このサンプルのようなツール類に対しては、コマンド名がそのまま使われていることがわかります。定数には、もっと他の設定もあります。ただし、この引数に NULL と kCFPreferencesAnyApplication(すべてのアプリケーション共通)を渡すことはできません。また、この部分に他のアプリケーションの環境設定ファイル名(通常は識別子だが、場合によっては違うだろう)を指定することで、別アプリケーションから他のアプリケーションの環境設定ファイルを変更することができます。これはアプリケーションの表面に出ない設定を修正したりするツールで使える手法です。
つぎに戻り値 value が NULL でないかチェックしています。CFPreferencesCopyAppValue 関数は、値が見つからなかった場合、NULL を返します。
値が見つかったら、2 で、CFNumber の関数を使って、その値を int に変換しています。この関数は、失敗したら false を返すので、その場合 highScore は 0 となります。それから値オブジェクトを解放し、highScore にコピーした int 値をメッセージとともに表示しています。値が返らなければ、以前の値がないというメッセージを表示し、0 を代入しています。
値があれば、変換はほぼ失敗することがないように思われるので、ここでのチェックは心配しすぎと思うかもしれません。しかし、上で書いたように、別アプリから環境設定値が変えられる可能性があります。もしかしたら、このアプリの実装を知らないツールが、勝手に文字列や他のオブジェクトをこれに設定しているかもしれません。そのため、値が適切かどうかを常にチェックしたほうがいいでしょう。
つぎに、3 で、値に 5 を加えて、それを記録することを告げるメッセージを表示し、保存用の CFNumber オブジェクトを作っています。もちろん、取得したものを修正して保存するのも可能ですが、ここではサンプルなので、アプリケーション等で通常行う手順として、まず初期化して、それからさまざまな操作を行い、最後に変更した設定を保存するときのように、別の CFNumber オブジェクトを扱っています。それから、CFPreferencesSetAppValue 関数で保存しています。引数は値が増えただけです。
最後に 4 で、環境設定の同期を行っています。これにより値が書き出されます。デバッガ等を使って停止しながら見てみれば、この時点で書き出しが行われていることを確認できるでしょう。
サンプル自体かなり簡単で、環境設定の扱いも簡単であることがわかると思います。軽く触れましたが、どういう単位で環境設定を保存するのか(ドメイン-複数アプリケーションをスイートとしてグループ化できる機能もある)など、通常と違う形で使用するときは、リファレンスやガイドを参照する必要があります。
管理人:神吉 秀典 E-mail: