第6章 デザインパターン | ||
ホーム | メール | |
目次 | < 前ページ 次ページ > |
前項ではリファレンスでwindowメソッドを探しましたが、NSTextViewとNSButtonで大きな違いがあったことに気づきかれましたでしょうか。
NSTextViewではdelegate methodがそこそこ並んでいました。しかしNSButtonにはdelegate methodはひとつもありませんでした。そしてNSTextViewにはデリゲートの接続先を設定するsetDelegateメソッドがありましたが、NSButtonにはNSButton自身にもそしてルートクラスまでのどのスーパークラスにもsetDelegateメソッドはありませんでした。
また、NSButtonではスーパークラスのNSControlでsetTargetメソッドとsetActionメソッドが定義されていましたが、NSTextViewでは自身も含めてどのスーパークラスにもこの2つのメソッドは定義されていませんでした。
すべてがこのケースにあてはまるとは限りませんが、ボタンのように「ボタンをクリックする」というトリガーしか存在しない場合はターゲットアクションが設定できるようになっており、テキストビューのようにいろいろなトリガーが考えられる場合はデリゲートに任せるという使い分けがされていることがある程度見えてくると思います。
ここではそのターゲットアクションをコーディングによって設定したいと思いますが「○○メソッドはスーパークラスで、○○メソッドはスーパークラスのスーパクラスで定義されている」と継承の階層と各クラスが何を担当しているのかが少し複雑になってきました。混乱されてきたら前述の「継承階層図」を見るようにしてください。なお、Objective-Cでこのように深い継承階層になっているものはボタンやビューなどのGUIパーツだけだと言えます。
<▽コメント>編集者様。ここにもう一度継承階層図をいれましょうか?。同じもので結構ですので<△コメント>
継承階層図を見れば分かるとおり、setTargetメソッドとsetActionメソッドはNSControlで定義されています。リファレンスウィンドウでNSControl Class Referenceを開いてみてください。下にスクロールしていくとImplementing the Target/action Mechanismというグループに目指す2つのメソッドがあります。それぞれをクリックして詳細も見ておきましょう。
それぞれのシグネチャが次のとおりであることが確認できると思います。
- (void)setTarget:(id)anObject - (void)setAction:(SEL)aSelector
setTarget:メソッドは引数としてメソッドを実装したオブジェクトを設定するということは分かりやすいと思います。しかしsetAction:メソッドの引数(SEL)aSelectorは意味が分からないと思います。今まではメッセージ式で [レシーバ メッセージ]のメッセージ部分にメソッド名をそのまま書いていました。この「メッセージ」の部分を正しくはセレクタと呼びますが、セレクタ(メソッド名)はプログラム内部(処理系内部)では文字列ではなくSEL型というデータ型として管理されています。setAction:メソッドではそのSEL型の引数を求めています。このSEL型の値を取得するには
@selector(メソッド名)
と記述します。
それでは、それぞれのシグネチャが分かったところでController.hのコーディングからはじめましょう。
強調表示されているコードを追加、もしくは変更してください。
#import <Cocoa/Cocoa.h> #import "Model.h" @interface Controller : NSObject { Model *model; IBOutlet NSTextView *textView; IBOutlet NSButton *button; } - (void)indicate:(id)sender; @end
IBOutlet NSButton *button;
Controller.mからPush Buttonにメッセージを送るために使うインスタンス変数を宣言しています。
(void)indicate:(id)sender;
Interface Builderから認識される必要がなくなりましたので、IBOutletからvoidに戻しています。
Controller.mで変更するメソッドはこの2つになります。強調表示されているコードを追加、もしくは変更してください。
- (void)awakeFromNib { [textView setString:@""]; [textView setDelegate:self]; [button setTarget:self]; [button setAction:@selector(indicate:)]; } - (void)indicate:(id)sender { NSLog(@"%@", [model string]); [[sender window] setDocumentEdited:NO]; }
[button setTarget:self];
Push ButtonのターゲットにこのControllerオブジェクト自身を設定しています
[button setAction:@selector(indicate:)];
Push ButtonのアクションにindicateメソッドのSEL型を設定しています。この時に@selector(メソッド名)のメソッド名の箇所に、メソッドに引数がある事を示すコロン : を忘れないように気をつけてください。なお引数のないメソッドを指定する場合はコロンを付ける必要はありません。
(void)indicate:(id)sender
Controller.hのプロトタイプ(メソッド宣言)に合わせて、こちらも戻り値をvoid型にしています。
コーディング作業は以上で終わりです。プロジェクトフォルダ(プロジェクトファイル)を保存してください。次にInterface Buildernでの設定を行います。
MainMenu.xibを開きます。メインウィンドウのIndicateボタンを右クリック、もしくはcontrol + クリックしてください。接続先の一覧が表示されますのでSent Actionsグループのindicate: Controllerの×印をクリックして接続を解除します。
図 アクションの接続解除
次にMainMene.xibウィンドウのControllerからPush Buttonnへ向けて接続線を引きます。そして現れるOutletsの中に現れるひとつだけの接続先buttonをクリック選びます。
図 Controllerアウトレットの接続
Interface Builderでの作業も以上で終わりです。ファイルを保存してInterface Builderを閉じるか、もしくは終了してください。
コンソールウィンドウを表示して「ビルドして進行」をクリックしてください。ビルドが終了しましたらいろいろと試しみてください。以前とまったく同じ動きをすると思います。
お疲れさまでした :-)
これで本章を終了します。次の章に進む前にこの節のプロジェクトのバックアップをされることをおすすめします。
目次 | < 前ページ 次ページ > |