● Carbon視点でiPhone探求(2010/07/09)

  この記事は、MOSAの会員にのみ読むことができるデベロッパー向けの
  ウェブサイトMOSADeN Onlineのに掲載された記事です。ほぼ一ヶ月
  遅れでここに掲載されて行きます。

  〜 環境設定の使い方(その1) 〜


今回と次回で、しんぶんしアプリの「環境設定」(User Default)を用意します。このアプリケーションの場合、環境設定で設定するようなオプションをあまり思いつかないのですが、何か無理やり捻出して試してみます。

環境設定とは何でしょうか?アプリケーションのある機能に対してユーザが選択できるオプションが幾つかあるとします。例えばペイントアプリなら、ペン描画する線の太さとかカラーなどです。ユーザはアプリを終了しても、次に起動した時に最後に選択した状態を復帰させたいわけです。そうした最終使用パラメータ(線の太さ、カラー)をファイルに保存しておいて、次回の起動時に読み込んで適切に再設定します。 これにより個々のユーザにとっての使いやすい(慣れ親しんだ)動作環境を保持できるわけです。

今回は、具体例として対称画像を「写真」アプリの写真アルバムに保存する時にサウンドを鳴らすオプションを付けてみます。例えば「メール」アプリではメール転送時に「シュ〜」という音が鳴ります。あんな感じのサウンドが鳴れば、アラートを表示しなくても「保存できた」という安心感をユーザに与えられます。このオプションがONの場合には「保存」ボタンをタップし保存が成功した時にサウンドが鳴ります。 逆に「音がうるさい」と感じるユーザは、このオプションをOFFにすればOKです。 OFFでは、前回と同様に「保存できました。」とアラート表示をすることにします。

Mac OS XのCocoaアプリケーションやiPhoneアプリケーションで環境設定を取り扱うにはNSUserDefaultsクラスを利用します。このクラスを利用すると、複雑な手続きをしなくても、各種オプションパラメータ(オブジェクト)の管理とファイルへの書き込み読み出しを受け持ってくれます。今回は、NSUserDefaultsクラスを利用するためのモデルコントローラであるPreferencesクラスを別途作成してみます。まず最初にSymmetryAppDelegate.hにPreferencesクラスのインスタンス変数であるap_prefを用意します。

@class  Preferences;
@class  Document;
@class  Model;

@interface SymmetryAppDelegate : NSObject <UIApplicationDelegate>
{
  UIWindow       *window;
  UINavigationController *navigationController; 
 
  Document       *ap_document; // メインドキュメントオブジェクト  
  Preferences      *ap_pref;    // 環境設定オブジェクト(保存用)
}

アプリケーション起動時に呼ばれるapplicationDidFinishLaunching:デリゲートメソッドでPreferencesオブジェクトを作成し、それをap_prefへ代入します。この処理が上手くいった場合には、PreferencesクラスのloadUserDefaultメソッドを使い、環境設定ファイルから必要なオプションパラメータを読み込みます。すぐ下のドキュメントの読み込み処理と似ていますね。

- (void)applicationDidFinishLaunching:(UIApplication *)application
{
  if( ap_pref=[[Preferences alloc] init] )   // 環境設定オブジェクトの作成
    [ap_pref loadUserDefault];      // 環境設定データの読み込み
    
  if( ap_document=[[Document alloc] init] ) // ドキュメント作成
  {
    if( [ap_document load]==NO )    // ドキュメント読み込み
    {
      //  ファイルの作成や読み込みが出来なかった(でエラー処理)
    }
  }
  [UIApplication sharedApplication].statusBarStyle=UIStatusBarStyleBlackOpaque;
  [window addSubview:[navigationController view]];
  [window makeKeyAndVisible]; 
}

そしてアプリケーション終了時には、PreferencesクラスのsaveUserDefaultメソッドを使い環境設定ファイルへすべてのパラメータを書き出します。もし、アプリケーションのクラッシュにより設定の変更操作が台無しになるのが嫌な場合には、パラメータ変更する度にパラメータをファイルへ書き出した方が良いでしょう(ドキュメント処理と同様)。

- (void)applicationWillTerminate:(UIApplication *)application
{
  [ap_document save];     // ドキュメント保存
  [ap_pref saveUserDefault];  // 環境設定を保存
}

続いてPreferencesクラスの定義です(Preferences.h)。ここではインスタンス変数のdefalutArray( NSMutableArray)をひとつだけ用意します。

@interface Preferences : NSObject
{
  NSMutableArray  *defalutArray; // ユーザディフォルト配列
}

NSUserDefaultsクラスを使うと、ファイルから「キー」(通常はNSStringを使う)の指定により環境設定に用いるパラメータ(各種オブジェクト)を読み込めます。同様にキーを付けたパラメータも書き込めます。このキーによる操作は、対象オブジェクトがディクショナリ(NSMutableDictionary)だと思えば理解しやすいでしょう。数値情報ならNSNumberにラップし、文字列ならNSString、日付ならNSDate、カラー情報ならUIColorオブジェクトを利用することになります。つまり、3つのパラメータを保存したければ、3つのキーと3つのオブジェクトを用意します。ちなみに、NSUserDefaultsクラスで「環境設定」を実現したApple社のサンプルソースコードはいくつもあります。

一般的な方法はそちらを参照してもらうとして、 ここでは少し変わった方法を取ってみます。本アプリのように環境設定に用意するオプションが少なければキーでの管理は簡単ですが、アプリケーションの規模によっては何十や何百の数値や文字列を環境設定に保存しなければいけない場合もあります。そこで、本アプリでは環境設定パラメータをキーで管理せず、配列のインデックスで管理してみます(本当はキーの方が楽ですが...)。環境設定ファイルへ保存するのは「UserDefault」キーで保存したNSMutableArrayオブジェクトのみとします。それをインスタンス変数として用意したdefalutArrayへ保存し管理します。以下が唯一のオブジェクト(配列)を読み込むためのloadUserDefaultメソッドです。

- (void)loadUserDefault  //  環境設定の読み込み
{
  NSUserDefaults *user;
  NSDictionary  *dict;
    
  user=[NSUserDefaults standardUserDefaults]; // ユーザディフォルトを得る
  if( defalutArray=[[user arrayForKey:@"UserDefault"] mutableCopy] )
  {                 // 環境設定パラメータ(配列)を得る
    if( [[defalutArray objectAtIndex:0] intValue] < APP_VERSION )
      [self updateUserDefault];  // バージョンにより必要ならアップデート
  }
  else // 初期設定が保存されていない場合
  {
    [self initUserDefault]; // デフォルト値による初期化
    dict=[NSDictionary dictionaryWithObject:defalutArray forKey:@"UserDefault"]; // デフォルト値の作成
    [user registerDefaults:dict]; // デフォルト値の登録
    [user synchronize]; // 外部記憶へ書き出し
  }
}

環境設定ファイルには、必ずアプリケーションのバージョン番号を保存することをお勧めします。これは環境設定のオプション内容がアップデートされた時に役立ちます。今回の場合、配列1つ目にアプリケーションのバージョン番号(1000=1.0.0.0)がNSNumberオブジェクトとして保存されています。ファイルから読み込んだバージョン番号が現在の番号よりも低ければ、アプリケーションはバージョンアップされ環境設定ファイルの内容更新をしなければいけない可能性があります(変更は無用かもしれませんが...)。そこで、アップデート処理を行うためにupdateUserDefaultメソッドを呼び出しています。

環境設定ファイルが存在しない場合には、initUserDefaultでディフォルトの配列を作成し、それをNSDictionaryに代入してから、registerDefaults:メソッドでディフォルトとして登録してsynchronizeメソッドでファイルへ保存します。この処理で利用しているupdateUserDefaultとinitUserDefaultの両メソッドはPreferenceクラスに実装することになりますので、次回にその詳細を解説します。

パラメータに何らかの変更がなされた場合、もしくはアプリケーションの終了時には NSUserDefaultsクラスのsetObject:メソッドで環境設定ファイルへと書き出します。

- (void)saveUserDefault  //  環境設定の保存
{
  [[NSUserDefaults standardUserDefaults] setObject:defalutArray forKey:@"UserDefault"];
}

また、iPhone OSには環境設定をアプリケーションの外で管理する仕組みがあります。簡単に説明すると「Root.plist」というXMLファイルに環境設定用のオプションキーと内容を記述して保存すれば、ルール従い「設定」アプリが上記の仕組みを代行します。そうして設定されたパラメータは、アプリケーション側から読み込むことが可能です。ただし、この方法では一旦iPhoneアプリを終了させる必要があるので、どちらの仕組みが自作アプリに向いているかは熟考が必要です。ユーザが滅多に変更しないオプションならば「設定」に任せても良いでしょうが、下手すると環境設定があることを知らないユーザを増加させてしまいます(笑)。

Root.plistの使い方を調べるのには、Apple社が提供しているサンプルソースコード「MoviePlayer」が大変参考になります。参照してみてください。

http://developer.apple.com/iphone/library/samplecode/MoviePlayer_iPhone/Introduction/Intro.html

  

  

  

次回は今回の続きです。環境設定ファイルとして確保した配列(NSMutableArray)からパラメータを出し入れする処理を実装します。そして、そのパラメータを利用し、対称画像を登録する時のサウンド発生のON/OFFを管理するようにします。

copyright 2010 Ottimo, Inc. All rights reserved
無断転載・引用禁止