|
|
3. モデル
モデル
MVC (モデルビューコントローラー Model-View-Controller) におけるモデル (Model) とはそのアプリケーションが扱う主となるデータとそのデータの出し入れ・変更・計算を行う実行部分(メソッド)を受け持つオブジェクトです。そしてまたユーザーの目からもっとも隠されている部分です。
MVCの各パートを受け持つオブジェクトは必ずしも1つでなければならないとは限りませんがモデルオブジェクトの場合は概ね1つでしょう。それに対してユーザーの目に触れユーザーからの操作を受け取るビューオブジェクト(ボタンやウィンドウ)は多数のオブジェクトから構成されます。そしてそのまとめ役でありビューとモデルの間の橋渡しをするのがコントロールオブジェクトです。Cocoa フレームワークにおいては (あるいは Objective-C においては) その構造上コントロールオブジェクトは必ず必要になります。シンプルなアプリケーションならコントロールオブジェクトがモデルオブジェクトを兼ねる場合もあります。
なおモデルを考える場合に一番イメージしやすいのはやはり顧客データのような名簿的なデータとそのデータを追加、変更、削除したりあるいはそのデータに対してなにがしかの計算を行う実行部分でしょう。 オブジェクトとはデータと実行部分から成り立っていることを思い出してください。
モデルクラスの作成
前回作成した Introducer プロジェクトファイルを開いてください。「グループとファイル」の中からClasses フォルダを選択します。今はまだ何も入っていないと思います。
Classes フォルダを選択した状態で、メニューバーから「ファイル」→「新規ファイル...」を選びます。
「新規ファイル」アシスタントが立ち上がります。Objective-C class を選択して「次へ」を押します
次の画面でファイル名を ITModel.m にしてください。「同時に"ITModel.h"も作成」にはチェックが入っていると思います。そのままにしておいてください。「保存場所」「プロジェクトに追加」「ターゲット」の各項目もデフォルトのままで正しいものが選択されていると思います。「完了」をクリックします
すぐに ITModel.h ファイルが開くと思いますが一旦それは閉じてプロジェクトウィンドウを確認してみましょう。無事に Classes フォルダに ITModel クラスのヘッダファイルと実装ファイルが出来上がっています。
モデルクラスのインターフェースを宣言する
ITModel.h (ヘッダファイル) をダブルクリックして開き以下のようにコーディングします。
ファイルを作成した時に自動的に1〜12行目までとインスタンス変数を書き込む波括弧および最後の @end は記述されていたと思います。1〜7行目までは先頭に // を付けた1行コメントです。ここにファイル名・プログラム名・作成者と日時およびクレジットが自動で記述されます。コメントですのでコンパイルには一切影響を与えません。
9行目の #import もコマンドラインプログラムの場合とは違い、Foundation フレームワークのヘッダファイルと GUI クラスの定義をしている ApplicationKit フレームワークのヘッダファイルをまとまて読み込む Cocoa.h が指定されています。そして12行目でははじめから NSObject のサブクラスとして記述されていたことだろうと思います。
インスタンス変数の宣言とアクセサメソッドの自動合成
インスタンス変数の宣言は learn ObjC Lite の intro プログラムとまったく同じです。またアクサセメソッドの宣言を自動合成するコードも learn ObjC Lite の intro プログラムとまったく同じです。アクサセメソッドの自動合成については
learnObjC 第3回 プロパティ もしくは
learn ObjC Lite 第3回 プロパティ をご覧になってください。
なお最近のアップルのドキュメントではインスタンス変数をメンバ変数と呼び、クラスのインタフェース部でのメソッド宣言(アクサセメソッドを含む)をプロトタイプと呼んでいるみたいです。C++ などと表現の仕方に統一がとれてこのほうが分かりやすいように思います。また汎用のオブジェクト型を表す id 型の使用はプログラミング的理由がない限りできるだけ使用を控えるようにとも書いてあります。
メソッドの宣言
この ITModel クラスではアクサセメソッド以外に次の4つのメソッドを宣言しています。
- (NSString *)showIntro:(NSString *)name;
dictionary に引数 name と同じキーがあればその値 (自己紹介文) を返します。同じキーが存在しなければ nil が返されます
- (BOOL)addIntro:(NSString *)message name:(NSString *)name;
dictionary に引数 message の値 (文字列オブジェクト) と引数 name キーのエントリーを追加して YES を返します。もし同じ値を持つエントリーが存在していた場合は追加せずに NO を返します。
- (BOOL)removeIntro:(NSString *)name;
dictionary から引数 name と同じキーを持つエントリーを削除して YES を返します。同じキーのエントリーが存在しなければ何もせずに NO を返します。
- (void)writeFile;
dictionary の内容 (データ) を指定されたファイルに書き出します。またこれに相対する「ファイルの読み出し」コードは親クラスである NSObject から継承した init メソッドの中に記述しています。
モデルのメソッドを実装する
プロジェクトウィンドウで ITModel.m をダブルクリックで開いて次のコードを記述してください。
@synthesize ディレクティブ
@synthesize ディレクブ(指示子)を使って ITModel.h において @property 指示子でメソッド宣言を自動合成したメンバ変数のメソッド実装も自動合成しています。詳しくは
learnObjC 第3回 プロパティ もしくは
learn ObjC Lite 第3回 プロパティ を参照してください。
init メソッド
learn ObjC Lite の init メソッドとまったく同じです。唯一違うのは書き出すファイル名が ZZIntro.plist から ZZIntroducer.plist に変わった点だけです。learn ObjC Lite に簡単な説明が載っています。気になる方は
learn ObjC Lite 第4回 コレクション の「コード説明」をご覧ください。ただし本当に簡単な説明だけです。
showIntro メソッド
23行目の objectForKey: インスタンスメソッドはレシーバーの NSDictionary オブジェクトの中から引数のキーと合致するエントリーを探してその値オブジェクトを返します。今回の値オブジェクトは NSString 文字列オブジェクトです。もしキーと合致するエントリーがない場合は存在しないことを表す nil が返されます。
addIntro メソッド
28行目の if 文の条件式では && 演算子で3つの条件が揃わないと次に進めなくなっています
・[ditionary objectForKey:name] == nil
このメッセージ式については showIntro メソッドで説明済みです。
・![message isEqualToString:@""]
isEqualToString メソッドは引数の文字列オブジェクトとレシーバーの文字列オブジェクトが同じ内容の文字列かどうかを確認します。同じであれば YES、違っていれば NO を返します。ここでは最初に ! (Not演算子)で「@""(未記入)と同じでなければ(未記入でなければ)」という意味になります
・![name isEqualToString:@""] も同じです。レシーバーが違うだけです
以上3つの条件を合せると、name キーと合致するエントリーがなく name フィールドと message フィールドが未記入でなければ次の式が実行されます
[dictionary setObject:値オブジェクト forKey:キーオブジェクト];
このメッセージ式で dictionary に引数のキーと値のエントリーを追加します。そして BOOL 値の YES を返します。if 文の条件式に合致しない場合はエントリーの追加は行われずに NO を返すだけです
removeIntro メソッド
if 文の条件式の意味はもう分かると思います。
38行目の [dictionary removeObjectForKey:name]; はレシーバーの dictionary から引数 name と同じキーを持つエントリーを削除します。そして削除された場合は YES を、name キーに合致するエントリーがなければ何もせずに NO を返します
writeFile メソッド
[dictionary writeToFile:書き出したいファイルまでのパスを表す文字列オブジェクト atomically:BOOL 値];
writeToFile: atomically: メソッドはレシーバーの NSDictionary か NSArray を引数で指定したファイルに plist として書き出します。plist として書き出しできるのは NSArray か NSDictionary のデータだけです。キーワード atomically: では引数に YES を指定すると一旦一時ファイルにデータを書き出してからあらためて指定されたファイルにデータを書き出します。NO を指定すると指定されたファイルに直接データを書き出します。
お疲れさまでした。これで Cocoa GUI App 第3回は終ります。
|
|
|