前回は、詳細ビュー表示の下準備としてDetailController.m以外のソースコード部分を説明しました。今回は、引き続きDetailViewControllerクラス(DetailViewController.m)の実装を解説いたします。

以下が、DetailViewController.mの開始部分です。前回のDetailViewController.hでの定義において、名称変更の対象となるモデルオブジェクト(de_model )をプロパティとして定義しましたので、ここでは@synthesize定義を行っておきます。これにより、コンパイラが自動的に、このプロパティのアクセッサメソッドを作成してくれます。そしてまず最初に viewDidLoadメソッドをオーバライドします。
#import "DetailViewController.h"
#import "SymmetryAppDelegate.h"
#import "Model.h"
@implementation DetailViewController
@synthesize de_model;
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.rightBarButtonItem=de_save; // 保存ボタンを追加
self.view.backgroundColor=[UIColor groupTableViewBackgroundColor]; // 背景をテーブルパタンに
de_text.delegate=self; // テキストフィールドデリゲート
}
viewDidLoadは、ビューコントローラがnib(xib)ファイルから作成される時点で呼ばれます。ここでは、ナビゲーションバーの右側に「保存」ボタンを表示し、文字入力カラムを配置するビューの背景をテーブルビューの背景と同じパタン(薄いブルーの縦じま)に設定しています。最後に、テキストフィールド(UITextField)のデリゲートを自分自身(self)に設定すれば処理は終了です。
ところで、iPhone OS 2.xまでは、メモリの使用状況がタイトになると、ビューコントローラに対してdidReceiveMemoryWarningメソッドが呼ばれ、そこで不必要なオブジェクト解放することが推奨されていました。ビューコントローラ自体は、この時点で制御していたビューなどを解放してメモリ使用量を落とすよう努力します。こうした状況が起こるのは、そのビューコントローラが表示されていない場合に限ります。例えば、別のビューコントローラをプッシュして自分自身は一時的に隠れているような場合です。
iPhone OS 3.xからは同じような状況になると、以下のviewDidUnloadメソッドも呼ばれます。ここでは、viewDidLoadで確保したオブジェクトを解放する必要があります。
- (void)viewDidUnload
{
[super viewDidUnload];
// ここでオブジェクトを解放させる
}
何故かと言うと、viewDidUnloadが一度呼ばれると、次にビューコントローラが表示される時に、もう一度viewDidLoadが呼ばれることになるからです。つまり、viewDidLoadで確保したオブジェクトを解放しておかないと、2度同じオブジェクトを確保してしまう(つまりメモリーリーク)する可能性があるわけです。 ちょうど、viewWillAppearとviewWillDisappearの関係と同じですね。 ちなみに、今回のアプリではそうした処理は不必要でしたので、viewDidUnloadはオーバライドしていません。
メモリ不足の警告については、iPhoneシミュレーターの「ハードウェア」メニューの「メモリ警告をシミュレート」で強制的に発生させることが可能です。アプリのリリース前には、必ずこうした実験を行い、デバイスへインストールした場合でも問題が無いか調べておく必要があります。この時に、viewDidUnloadやdidReceiveMemoryWarningでの処理に何か間違いがあると、次の機会に同じビューコントローラを表示した時に、アプリが異常終了したりメモリーリークが起こる場合があります。注意しましょう!
続いて、viewWillAppearをオーバライドします。ここでは、対象となるモデルに設定されている画像の名称をテキストフィールドに代入しておきます。
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
de_text.text=de_model.md_name; // 画像名を設定する
}
こちらは、viewWillDisappearのオーバライドです。テキスト編集を終了し(キーボードを引っ込める)retainして確保しておいた対象モデルオブジェクト(de_model)にreleaseを送ります。
- (void)viewWillDisappear:(BOOL)animated
{
[super viewDidAppear:animated];
[de_text endEditing:NO]; // テキスト編集を終了する(キーボードを消す)
self.de_model=nil; // 対象モデルオブジェクトを解放する(releaseする)
}
次は「保存」ボタンをタップした時のアクションメソッドです。テキストフィールドに入力されている文字列を対象となるモデルオブジェクトに代入してから、ビューコントローラをポップして、表示を「画像一覧」のテーブルビューに戻します。
- (IBAction)saveName:(id)sender
{
SymmetryAppDelegate *app;
if( [de_text.text length] ) // テキストが入力されていたら...
de_model.md_name=de_text.text; // モデルオブジェクトに設定する
app=[[UIApplication sharedApplication] delegate];
// アプリケーションデリゲート を得る
[app popViewController]; // ビューコントローラをポップする(一覧に戻す)
}
また同様に、キーボードでreturnキーをタップした時には「保存」ボタンをタップしたのと同じ挙動をさせます。これを実現するには、テキストフィールド(UITextField)のデリゲートメソッドであるtextFieldShouldReturn:を実装します。つまり、前回のDetailViewController.hで指定しておいたUITextFieldDelegateプロトコルに準拠させるわけです。
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[self saveName:self]; // テキスト(名前)保存処理
return YES;
}

さて、これで画像の名称変更が可能になりました。次回からは「画像の対称処理(シンメトリー処理)」について解説いたします。画像を直接操作するために、CoreGraphicsやQuartzCore Frameworkの登場となります。