修正日: 07/09/05  
 練習問題9   
 解答編
解答例です。初期設定への読み書きそのものは解説の部分でほとんど例示してしまったので、特に問題は無いと思います。問題はどこでその処理を行うか、です。解答サンプルはこちら。
まずは初期設定データの読み書きを行う部分を紹介します。
//初期設定の読み込み
- (void)loadUserDefaults
{
  NSUserDefaults  *aDefault=[NSUserDefaults standardUserDefaults];
  if([aDefault floatForKey:@"height"])
    height=[aDefault floatForKey:@"height"];
  else
    height=[heightField floatValue];
    
  if([aDefault floatForKey:@"weight"])
    weight=[aDefault floatForKey:@"weight"];
  else
    weight=[weightField floatValue];
}
//初期設定の保存
- (void)saveUserDefaults
{
  NSUserDefaults  *aDefault=[NSUserDefaults standardUserDefaults];
  [aDefault setFloat:height forKey:@"height"];
  [aDefault setFloat:weight forKey:@"weight"];
  [aDefault synchronize];
}例と違うのは読み込みの部分でifを使って分岐している点です。これは初めての起動のときは身長体重が0にセットされてしまうのを防ぐ目的でこうしてあります。もう少し短く書くこともできますが、コードが読みにくくなるので若干冗長な書き方をしてあります。
で問題はこの二つのメソッドをどこで呼ぶかです。読み込みのメソッドは考えるまでもなく「awakeFromNib」で呼べばOKですね。では保存はどこで行えば良いでしょうか?もちろん「アプリケーションが終了する前」ですが、これはどのように実装すれば良いのでしょうか?
実はこれについては練習問題6の解答で既に説明してあります。読み直してみてください。
・・・NSAppの「NSApplicationWillTerminateNotification」ノーティフィケーションをつかまえてやれば良いのです。ということでこんな感じ。
- (void)awakeFromNib
{
  NSNotificationCenter  *aCenter=[NSNotificationCenter defaultCenter];
  [aCenter addObserver:NSApp
      selector:@selector(terminate:)
      name:@"NSWindowWillCloseNotification"
      object:bmiWindow];
  [aCenter addObserver:self
      selector:@selector(applicationWillTerminate:)
      name:@"NSApplicationWillTerminateNotification"
      object:NSApp];
  //初期設定の保存
  [self loadUserDefaults];
  //BMIを計算して結果をすべてのコントロールにセット
  [self calcBMIAndSet];
}
- (void)applicationWillTerminate:(NSNotification *)pNotification
{
  //初期設定の保存
  [self saveUserDefaults];
}ノーティフィケーションについては練習問題6を読みかえしてみてください。
これで起動するたびに前回に設定した身長と体重が表示されるようになります。試してみてください。
そうそう、最後に一つ、初期設定を扱う上で大事なことを追記しておきます。初期設定ファイルの名前はアプリケーションのプロパティの「識別子」の設定に依存します。プロジェクトウィンドウの「ターゲット」の下のアプリケーション名を選択してCommand+iで情報ウィンドウが開きますので、プロパティタブで編集することができます。

ここでは識別子を「learnCocoa.sekn.CalcBmi」にしてありますので、初期設定ファイルは「learnCocoa.sekn.CalcBmi.plist」という名前で表示されます。この識別子に特別なルールは内容ですが一般的には「com.会社名.プロダクト名」という感じで設定しているようです。独自のドメインを持っている場合はその逆をセットすれば良いでしょう(例えば「hogehoge.net」さんであれば「net.hogehoge.appname」という感じ)。一度セットすると後で変えるのは大変なので、公開する前によく考えましょう。