今回は次回の続きです。環境設定ファイルとして確保した配列(NSMutableArray)からパラメータを出し入れする処理を実装します。そして、そのパラメータを利用し、対称画像を登録する時のサウンド発生のON/OFFを管理するようにします。
今回から「しんぶんし」のプロジェクトをiOS 4.0に対応させることにします。そのために利用する開発ツールをXcode 3.2.3に切り替えますのでご了承ください。iOS 4.0対応といっても、4.0特有の機能はまだ何も使いません。今まで通りiOS 3.1.3コンパチブルとしたいので、ビルド設定の「iPhone OS Deployment Target」は、3.1.3と設定しておきます。これにより、iOS 3.1.3のデバイスにも「しんぶんし」をインストールすることが可能です。また、iOS 4.0を搭載したデバイスにインストールすると、何もしなくても高速アプリケーション切り替え機能(メモリ常駐)に対応したことになります。

本アプリでは、環境設定のパラメータをCルーチンからアクセスできるようにしてみます。そうする理由は単純で、環境設定のパラメータはあちこちのオブジェクト内で参照されますので、その度に、いちいちメッセージ送り先のPreferencesオブジェクトを得るのが面倒なためです。まず、 Preferences.mで初期化のinitメソッドをオーバライドし、作成したオブジェクトを外部変数のsys_prefへ代入しておきます。これにより、Cルーチン内でこのクラスのインスタンス変数であるdefalutArrayに直接アクセスできるようにります。ただし、この方法はオブジェクトを一つしか作らないクラス(シングルトン・パターンと呼ばれる)にしか適用できませんので御注意ください。
Preferences *sys_pref; // 環境設定コントローラ自身
- (id)init
{
if( self=[super init] )
sys_pref=self; // 環境設定インスタンス保存
return self;
}
これで、環境設定に保存されている整数(NSUInteger)パラメータへのインデックス経由の書き込みと読み込み(I/O)は、以下の様なCルーチンで可能となります。
void setPrefInteger( NSUInteger index,NSUInteger value ) // 書き込み
{
[sys_pref.defalutArray replaceObjectAtIndex:index withObject:[NSNumber numberWithInteger:value]];
}
NSUInteger getPrefInteger( NSUInteger index ) // 読み込み
{
return [[sys_pref.defalutArray objectAtIndex:index] intValue];
}
このルーチンを使う前に、インスタンス変数のdefalutArray(NSMutableArray)を作成し、先んじてオブジェクト配列へ初期値を代入しておきます。「しんぶんし」では利用しないのですが、例題として、整数だけでなく浮動小数点、日付、文字列を環境設定パラメータとして用意するケースを想定しておきます。整数パラメータは100個用意し、それ以外のパラメータは20個ずつ用意しています。また、整数パラメータの1つ目にはアプリケーションのバージョン番号を、2つ目には対象画像保存時にサウンドを鳴らすかどうかON/OFFのデフォルト値(今回はゼロ...鳴らさない)を代入しておきます。
#define APP_VERSION 1000 // バージョン番号(1.0.0.0)
#define MAX_PREF1 100 // 整数パラメータの数
#define MAX_PREF2 20 // その他のパラメータの数
- (void)initUserDefault // 環境設定の初期化
{
NSDate *date;
NSUInteger i;
if( defalutArray=[[NSMutableArray alloc] init] )
{
for( i=0;i<MAX_PREF1;i++ ) // 整数 初期化(100個)
[defalutArray addObject:[NSNumber numberWithInteger:0]];
for( i=0;i<MAX_PREF2;i++ ); // 浮動小数点 初期化(20個)
[defalutArray addObject:[NSNumber numberWithDouble:0.0]]
for( i=0;i<MAX_PREF2;i++ ) // 日付 初期化(1970.01.01)(20個)
{
date=[NSDate dateWithTimeIntervalSince1970:0];
[defalutArray addObject:date];
}
for( i=0;i<MAX_PREF2;i++ ) // 文字列 初期化(ヌル文字列)(20個)
[defalutArray addObject:@""];
setPrefInteger( 0,APP_VERSION ); // 00番.バージョン番号(1.0.0.0)
setPrefInteger( 1,0 ); // 01番.画像保存でサウンドを鳴らす(ON/OFF)
}
}
それから、前回紹介したPreferencesクラスのsaveUserDefaultメソッドですが、アプリケーション終了時だけでなくパラメータ変更時にも呼べるよう、synchronizeメソッドを追加してファイルへの逐次保存を追加しておきます。
- (void)saveUserDefault // 環境設定の保存
{
NSUserDefaults *user;
user=[NSUserDefaults standardUserDefaults];
[user setObject:defalutArray forKey:@"UserDefault"]; // 環境設定を保存
[user synchronize]; // 外部記憶へ書き出し
}
続いて、AboutViewController.hに環境設定パラメータ用のスイッチ(UISwitch)のIBOutlet ab_switchを定義します。そしてInterface BuilderでAboutViewController.xibにスイッチをひとつだけ配置して、それをのab_switchとアクションメソッドのchangeState:へコネクトします。
@interface AboutViewController : UIViewController
{
IBOutlet UISwitch *ab_switch; // 環境設定用のスイッチコントロール
}
@property(nonatomic,assign)UISwitch *ab_switch;
- (IBAction)changeState:(id)sender // スイッチON/OFF変更のアクションメソッド
{
SymmetryAppDelegate *app;
setPrefInteger( 1,ab_switch.on ); // スイッチの状態をパラメータとして保存
app=[[UIApplication sharedApplication] delegate]; // アプリデリゲーター
[app.ap_pref saveUserDefault]; // 初期設定のファイル保存
}

アバウト表示時にスイッチのON/OFF状態を環境設定パラメータと一致させる必要がありますが、これについては、SymmetryAppDelegate.mに実装したopenAboutViewControllerメソッド(アバウトビューをオープンする)の最後に以下の一行を追加するだけでOKです。
aboutvctr.ab_switch.on=getPrefInteger( 1 ); // 環境設定スイッチのON/OFFセット
最後に対称画像の保存終了時に呼ばれるメソッドの修正です。今までは「画像を保存しました。」と言うメッセージを表示していましたが、今回からは、getPrefInteger( 1 )の内容により、メッセージ表示かサウンドを鳴らすのかを切り替える必要があります。
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
NSString *str,*ok;
BOOL sheet=YES;
UIAlertView *alertView;
if( ! error ) // 正常に保存
{
if( getPrefInteger( 1 ) ) // サウンド発生(ON)
{
sheet=NO; // シートは表示しない
sendSound();
}
else // 保存用アラート表示
str=NSLocalizedString( @"IMG_SAVED",@"" );
}
else // エラー発生
str=NSLocalizedString( @"IMG_ERROR",@"" ); // エラー用アラート表示
if( sheet==YES ) // シートを表示する場合
{
ok=NSLocalizedString( @"OK_BUTN",@"" );
alertView=[[UIAlertView alloc] initWithTitle:str message:nil delegate:nil cancelButtonTitle:nil otherButtonTitles:ok,nil];
[alertView show];
[alertView release];
}
}
発生させるサウンドは、お好みのサウンドファイル(send.wav)をResourcesフォルダへ保存して利用します。サウンドを鳴らすルーチンは、以前作成したsysBeep()を少しだけ改良して再利用しています。
AVAudioPlayer *send_beep;
void setupSendSound() // 画像保存用サウンド初期化ルーチン
{
NSString *path;
NSURL *url;
if( ! send_beep ) // 初期化されていなければファイルを読み込む
{
path=[[NSBundle mainBundle] pathForResource:@"send" ofType:@"wav"];
if( url=[NSURL fileURLWithPath:path] )
send_beep=[[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
}
}
void sendSound() // 画像保存用サウンドを鳴らすルーチン
{
setupSendSound();
if( send_beep )
{
send_beep.currentTime=0; // 再生位置は最初から
[send_beep play];
}
}

今回で「しんぶんし」について予定していた機能はほぼ実装されました。次回からは、このアプリをiPad用としても動かせるように改良してい行きたいと思います。ユーザインターフェースの大画面への対応や、モデルクラスのCore Dataへの変更などをについて解説できればと考えています。お楽しみに!