viva Cocoa Objective-C 入門 第6章 デザインパターン
ホーム メール
 
目次 < 前ページ 次ページ >

ターゲットアクション

 「デリゲート」の節では、入力のたびにModelオブジェクトに格納されている文字列がコンソールウィンドウに表示されました。しかしあれでは少し忙し過ぎましたね :-) 今度はModelオブジェクトの内容をコンソールに表示したいときにはボタンを押すようにします。じょじょにアプリケーションらしく変わっていきます。なおこのボタンはのちほど大事な役割を果たすことになります。

このページからCSS 3を使ってみることにしました。IE 9+、Opera 10.5+、Safari 4+、Firefox 3.5+でないと正しく表示されないと思います。非対応のブラウザでは前のページと同じ表示になります。しかしIE6などのかなり古いブラウザの場合は何も表示されない白紙状態になると思います。

 作業に入る前に前節までのバックアップをとることをおすすめします。バックアップはプロジェクトフォルダをまるごと複製(コピー)してください。そして複製したほうに新しい名前を付けます。私の場合は「MyClip 6.3」としました。MyClipの6章3節のプロジェクトという意味です。付ける名前はご自由で大丈夫です。またプロジェクトフォルダの名前を変更してもアプリケーション名やプロジェクト名が変更になることはありません。そして新しい作業は引き続いて最初のMyClipプロジェクトフォルダ内のMyClip.xcodeprojで行うようにします。このようにすればDockに登録したMyClip.xcodeprojやMyClipフォルダが常に使えることになります。

 なおバックアップの取り方についての説明は今回で2度目になります。次回からは単に「バックアップをとっておいてください」とだけ指示することにいたします。

ターゲットアクション

 ターゲットアクションはObjective-Cの中ではデリゲートよりも代表的なデザインパターンと言えるでしょう。しかしサンプリアプリケーショMyClipの作成過程と合わせるためにデリゲートの次に紹介することにいたしました。ここまでに登場してきたデザインパターン(設計様式)を登場順に記述すると次のようになります。

  1. シングルトンアプリケーション
  2. MVC
  3. デリゲート
  4. ターゲットアクション

 しかしこれを代表的な順番に並びかえると次のようになります。

  1. MVC
  2. シングルトンアプリケーション
  3. ターゲットアクション
  4. デリゲート

 この節でも、まずターゲットアクションの簡単な説明をいたします。次に実際の作業をしていただき。そしてそのあとでもう一度詳しい説明をしたいと思います。

■ ターゲットアクション

 ターゲットアクションとデリゲートはともにメソッドの実行をほかのオブジェクトに依頼しているという点では同じです。3章のオブジェクトの節でも説明したとおりにメソッドの実行を外注先に出しているわけです。しかしターゲットアクションとデリゲートで大きく違う点もあります。デリゲートではdelegateというインスタン変数にメソッドの実行を依頼するオブジェクトを接続しました。
 一方ターゲットアクションでもtargetというインスタン変数にメソッドの実行を依頼するオブジェクトを接続しますが、さらにもうひとつactionというインスタン変数に実行を依頼するメソッドのセレクターを登録します。この点が一番大きな違いと言えます。そしてもうひとつ、ターゲットアクションはNSControllerクラスを継承したクラスだけが持つことができます。言い換えればターゲットアクションはNSControllerクラスにおいて定義されています。そしてこれらのNSControllerのサブクラスはコントローラ、コントローラオブジェクト、コントローラクラスなどと呼ばれます。具体的なクラス名で言えばNSButton、NSSlider、NSTextFieldなどがあげられます。つまりターゲットアクションはGUIパーツの中のいくつかだけが持っているデザインパターンになります。
 ここでこの章で出てくるクラスの継承階層図を見てみましょう。すでに登場してきたものも、これから登場するものも含まれています。

■ 継承階層図

継承階層図の説明

 上からルートクラス→サブクラス→サブクラス→サブクラス→サブクラス(末端のクラス)という並びいなっていますが、矢印は上から下にではなく、下から上に伸びています。

 私たちは、このような継承関係を表す図としては家系図などを見なれていると思います。その感覚からすると矢印が下から伸びていることには違和感を覚えます。しかしこれはサブクラスがスーパークラスのすべてを含んでいるという関係、言い換えれば参照しているという関係を表しています。

 OOPの継承階層を表す場合にはこのようにサブクラスからスーパークラスへ矢印を引く決まりになっています。慣れるまでは少し気持ちが悪いかもしれませんが我慢してください。

 各クラスには代表的なメソッドを載せました。それぞれのクラスがどのような役割を担っているか確認してみてください。分かるメソッドもあれば分からないメソッドもあると思いますが、ひとつひとつリファレンスで確かめてみることをおすすめいたします。

ユーザインタフェースの作成

 では実際にMyClipにターゲットアクションの機能を追加してみましょう。

 前項の説明で分かっていただけと思いますがターゲットアクションは必ずGUIパーツ(ビューパーツ)に搭載することになります。ということはまずはInterface Builderでターゲットアクションを搭載するユーザインタフェース(GUIパーツ)を作成しなければなりません。なお実際のターゲットアクションの搭載はデリゲートの場合とおなじくInterface Builderで行うこともコーディングで行うこともできます。

■ 下準備

 Interface Builderでの作業の前にターゲットアクションの実行結果を確かめるための仕掛けを作っておきたいと思います。

Controller.mを開きtextDidChange:メソッドの次に

	- (IBAction)indicate:(id)sender
 というメソッドを追加します。そしてtextDidChange:メソッドから
	NSLog(@”%@”, [model string]);
 という式をindicate:メソッドに移動します。当然カット&ペーストで行ってもらって構いません。この作業でController.mのtextDidChange:メソッドとindicate:メソッドのコードは次のようになります。強調箇所が追加されたコードになります。
- (void)textDidChange:(NSNotification *)aNotification { [model setString:[[textView string] copy]]; } - (IBAction)indicate:(id)sender { NSLog(@"%@", [model string]); }
 この作業で何をしているかというと、Text Viewを書き変えるたびにModelオブジェクトのstringインスタン変数の値(文字列)がコンソールに表示されていたのを、indicate:メソッドが実行された時にだけコンソールに表示されるように変更しています。コーディングが終わりましたらController.mを保存してください。

 次にController.mのindicateメソッドのシグネチャをコピーします。コピーが終わりましたらController.mは閉じてもらっても結構です。なおindicate:メソッドのシグネチャとは次の部分のことになります。
	- (IBAction)indicate:(id)sender
 次にController.hを開きます。Contoroller.hの@endの前の行にさきほどコピーしたシグネチャをペーストします。ペーストしたシグネチャの最後に式の終わりを示す ; (セミコロン )を忘れずに付けてください。この作業でController.hのコードは次のようになります。強調表示された部分が追加されたコードです。
#import <Cocoa/Cocoa.h> #import "Model.h" @interface Controller : NSObject { Model *model; IBOutlet NSTextView *textView; } - (IBAction)indicate:(id)sender; @end
 この作業でController.hに追加されたのはindicateメソッドのプロトタイプ(メソッド宣言)です。戻り値としてIBActionと記述されていますが、IBActionと記述することによってInterface Builderでこのメソッドactionとしてを認識できるようになります。このactionメソッドの引数は
	(id)sender
とする決まりになっています。またIBActionという文字列はコンパイルに先立つプリプロセスでvoidに置き換えられます。

■ Interface Builder でのレイアウト

次にInterface Builderでの作業を行います。

 MainMenu.xibを起動してください。そしてメインウィンドウのタイトルバーをクリックするか、もしくはMainMenu.xibウィンドウでWindow(MyClip)オブジェクトをクリックします。インスペクタウィンドウのタイトルがWindow ○○になっていることを確認してください。

 次にメインウィンドウの中をクリックします。メインウィンドウの表示部全体が選択されてインスペクタパネルのタイトルがScroll View ○○になることを確認してください。もしScroll Viewが選択されていないようでしたら、メインウィンドウを選択するところからやり直してみてください。

 Scroll Viewを選択するとウィンドウの下辺の中央に小さい点(ドット)があることが分かると思います。

図 MyClipウィンドウ2

 次にこの点(ドット)をマウスでつかんで(ドラッグして)スクロールビューの下辺を少し上に持ち上げます。

図 MyClipウィンドウ3

 ライブラリパネルからPush Buttonを探して、メインウィンドウの下に空けたスペースにドラッグします。その際にレイアウトの目安となるガイドラインが現れますのでそれにあわせてボタンをドロップします。

図 Button レイアウト

 新しく配置したボタンが選択された状態のままインスペクタパネルでAttributesタブを選びます。インペクタパネルのタイトルが Button Attributesになっていることを確認してください。そしてTitle欄をIndicateにします。

図 Button Attributes

 同じく、Push Button を選択したまま「Layout」メニューから「Size to Fit」を選びます。ボタンがタイトル文字に合うサイズに変わります。ボタンのサイズが変わりましたのでもう一度ガイドラインにあわせてボタンの位置決めをしてください。

図 Layout - Size To Fit

 Scroll View を再び選択し下辺の丸い点をドラッグして現れるガイドラインにしたがってScrool Viewの下辺の位置を調整します。

図 Scroll View レイアウト

 以上でユーザインタフェースは完成いたしました。



目次 < 前ページ 次ページ >


Copyright 2006 - 2010 viva Cocoa. All Rights Reserved.