Interface Builder概要

Konton's iPhone application labolatory

English top page

Interface Builderとは

Interface BuilderはiPhone SDKの構成パーツの一つで、ユーザーインターフェースの設計に使われるツールです。ユーザーインターフェースに使う部品を画面に配置してゆくことで、 全体の画面設計をしてゆくことができます。

ただ、別にユーザーインターフェースの設計は全てこれで行わなければならないというものではありません。全部をInterface Builderで設計しても構いませんし、 部分的にだけ使っても構いません。全く使わないという選択肢もあります。多言語対応のソフトを作る場合だと、 現在ユーザーが設定している言語に従い、表示内容を変更しなければならなくなります。そのようなことをInterface Builderのみでやる場合は 各言語のファイルをそれぞれ用意することになるので、管理に手間がかかります。このように小回りの利かない部分はありますが、 アプリケーション開発の初期段階において画面デザインの試行錯誤をする場合などでは、全体のデザインが把握しやすい分Xcodeだけで開発を行うより有利でしょう。


XcodeからのInterface Builder起動

自分のプロジェクトのResorcesというグループを展開してみると、拡張子がxibのファイルが見られると思います。それをダブルクリックすることでInterface Builderが起動します。 Libraryにユーザーインターフェース用のパーツが入っているので、それをウインドウやビューに配置して画面上のインターフェースを設計してゆきます。 このファイルはObjective-C(cocoa)関連のドキュメントでnibファイルと書かれているため、ここでもnibファイルと呼ぶことにします。 ちなみにiPhone SDK 3.2よりiPadアプリケーションの開発が出来るようになりましたが、iPad用は専用部品の追加もあるためnibファイルも専用となります。 新規作成時にiPhone/iPod touch用か、iPad用かを選択するようになっています。 iPhone SDKの3.2より前のバージョンで作成したファイルは自動的にiPhone/iPad用となります。 ユニバーサルアプリケーションでもiPad専用の部品を使わなくて良い場合は、iPhone/iPod touch用のnibファイルをiPad用として使うこともできます。


IBOutletとIBAction

Xcode側とInterface Builder側をつなぐ架け橋になるのがIBOutletとIBActionの2つの言葉です。 IBOutletはそのメンバがInterfaceBuilder側で作成したパーツであることを知らせるために宣言するものです。 Xcode単独でユーザーインターフェースを構築する場合は自分でallocを書かなければなりませんが、Interface Builderを使えばその必要がなくなりますし、 位置や大きさなどもInterface Builder側で行った設計が反映されます。 ViewControllerなどのオブジェクトにとってはnibファイルも「自分の外の領域」になるため、IBOutletはヘッダ側での宣言に付けます。 @interfaceの中括弧内部で書いても、@propertyの側で書いても特に問題は無いようですが、 意味を考えると@property側に書いたほうが良いような気がします。この宣言が付いているメンバはInterface Builderでも見えるようになり、 Interface Builderのパーツとの間で関連付けを行えるようになります。

IBActionはそのオブジェクトの外部から見えるメソッドが、 Interface Builder側にあるパーツからのメッセージに対応するためのものであることを知らせるために付けます。メソッドの戻り値を書く括弧内へ記載することで、 Interface Builder側でもそのメソッドが見えるようになります。 これによりInterface Builderにあるパーツがユーザーからの操作で何らかのイベントメッセージを発生させた場合、 そのメッセージを受け取るためのメソッドとして選べるようになります。 このようにIBOutletとIBActionではその意味が異なるので、Interface Builder側で配置するパーツ次第でこれらのものと関連があるものや、全く無いものが出てきます。

例えばラベルの場合、そのラベルで表示する文字列をXcode側でいじる必要があるなら、そのラベルを示すUILabelをXcode側で宣言し、 そのプロパティにIBOutletをつけておく必要があります。 ですがラベルで何らかのユーザーアクションによるメッセージが発生することはまず無いので、IBActionメソッドを用意する必要は通常ありません。 画像で出来たボタンの場合、それをXcode側で操作する必要がないなら、IBOutletは不要ですが、 ボタンが押されたというイベントに対して何らかの反応を起こす必要はあるでしょうから、イベントに対応するIBActionメソッドを用意する必要があります。

なおこれらの宣言はヘッダを編集して書き足しただけの時点ではInterface Builderに反映されません。変更後にヘッダが保存されるとInterface Builder側にも変更が反映され、 書き足されたIBOutletやIBActionを認識します。


基本的なイベントの例

Did End On Exit

キーボードのリターンキーと呼ばれる、右下に表示されるキーが押された時に発生するイベントです。キーボードのリターンキーに表示させる文字はいろいろ選べますが、 押された場合の反応はプログラマ側で書く必要があります。リターンキー部分にGoogleやYahooと書いたボタンを表示させたからといって、 押された時に勝手に検索をしてくれるわけではありません。


Touch Up Inside

タッチパネルから指を離したときに発生するイベントです。UIButtonオブジェクトでこのイベントが発生した時、ボタンが押されたと判定します。 タッチパネル関連のイベントは他にも多数あります。


Value Changed

UISegmentControl、UITextField、UIDatePickerなどといったユーザーからの入力を受け付けるオブジェクトで、入力内容が変更された場合に発生するイベントです。 テキストフィールドなどは入力の確定まで放置でも問題ない場合が多いですが、値の変更毎に何らかの反応が必要な場合には、このイベントに対応するメソッドが必要になります。 似たような名前でEdithing Changedというのがあって混同しそうですが、それは編集/完了ボタンが押された時などに発生するイベントなので間違えないようにしましょう。


実例 - Did End On Exitを使ったテキストフィールド間の移動

実例としてDid End On Exitメッセージへの応答を使ったテキストフィールド間の移動方法を説明します。以下の例では一連の手順で実際に何を行っているのかがわかりやすいように、 XcodeとInterface Builde間を何度か移動しながら進行します。

1.まずXcodeで新規プロジェクトを作ります。テンプレートはView-Based Applicationを選びましょう。以降、プロジェクト名は「MoveField」と付けたものとして説明します。

2.Xcodeの左側のリストからResouscesを展開し、MoveFieldViewController.xibをダブルクリックします。

3.Interface Builderが起動しますので、開いたViewにLibraryからText Fieldを2個ドラッグします。ライブラリが表示されていない場合はメニューのToolsからLibraryを選んでください。

4.作成された2個のテキストフィールドをViewの左上に上下に並べて配置します。上のテキストフィールドはAttributesのReturn KeyをNextにします。 これも画面上で見えないならメニューのToolsからAttributes Inspectorを選べば表示されます。Return Keyの設定は中央付近にあります。 設定が終わったらXcodeに戻ります。

5.Xcodeに戻ったら、今度は左側のリストのClassesを展開し、MoveFieldViewController.hをクリックします。右下にヘッダファイルの内容が表示されたら、 「@interface~@end」の部分を以下のように変更します。

@interface MoveFieldViewController : UIViewController {
    UITextField *textField1, *textField2;
}

@property (nonatomic. ratain) IBOutlet UITextField *textField1, *textField2;

@end

簡単に説明すると、MoveFieldViewControllerのメンバにさきほどInterface Builde側で追加した2個のテキストフィールドへ対応させるポインタを2個宣言し、 それらのプロパティを設定しています。

6.変更を保存したら、次にMoveFieldViewController.mをクリックします。「@implementation~」で始まる行の下に@synthesizeを追加します。以下のように変更しましょう。

@implementation MoveFieldViewController
@synthesize textField1, textField2;

基本的に@propertyを付けたものには@synthesizeの追加が常にセットになると思っておけば間違いはないでしょう。

7.ファイルの一番下にある「- (void)dealloc」のメソッドを以下のように変更します。

- (void)dealloc {
    [textField1 release];
    [textField2 release];
    [super dealloc];
}

8.変更を保存したら、Interface Builderに戻ります。

9.リストのFile's Ownerの上にマウスカーソルを置き、Ctrlを押しながらマウスボタンをクリックします。 Windows用の2ボタンマウスをつないでいる場合は右クリックすればOKです。 黒っぽいウインドウが開きます。そのウインドウのOutletsに先ほど追加したtextField1とtextField2が見えるはずです。textField1の右側にある○でマウスボタンを押し、 マウスボタンを押したまま、Viewに配置した上側のテキストフィールドの上へとマウスカーソルを動かし、マウスのボタンを離します。 これで、「Xcodeで宣言されているtextField1というのはこのテキストフィールドのことですよ」とInterface Builderに知らせることが出来ます。 この一連の操作を「紐付け」と呼ぶようです。

10.同様にtextField2と下側のテキストフィールドでもこの紐付けを行います。変更を保存したら、Xcodeに戻ります。

11.MoveFieldViewController.hを開き、先ほどの部分を以下のように変更します。

@interface MoveFieldViewController : UIViewController {
    UITextField *textField1, *textField2;
}

@property (nonatomic. ratain) IBOutlet UITextField *textField1, *textField2;

- (IBAction)pushNextButtonAtTextField1:(id)sender;

@end

@propertyの下に戻り値の部分をIBActionにしたメソッドの宣言を追加しています。

12.変更を保存したら、次にMoveFieldViewController.mを開きます。

13.先ほどの@synthesizeを追加した下に以下のようにヘッダでの宣言に対応するメソッド本体を追加します。

@implementation MoveFieldViewController
@synthesize textField1, textField2;

- (void)pushNextButtonAtTextField1:(id)sender {
    [textField2 becomeFirstResponder];
}

これは、textField2をfirstResponder、つまり「キーボードが表示された編集可能状態」にしなさいというメソッドになります。

14.変更を保存後、もう一度Interface Builderに戻ります。

15.先ほどと同様にFile's Ownerの黒いウインドウを出すと、Received Actionの項目に先ほど追加したpushNextButtonAtTextField1:が見えるはずです。 右側にある○でマウスボタンを押し、マウスボタンを押したままViewの上側にあるテキストフィールド上にマウスカーソルを動かし、そこでマウスボタンを離します。 開いた黒いウインドウからDid End On Exitを選びます。 これで、「上側のテキストフィールドの編集中にキーボードのReturn Keyが押されたら、下側のテキストフィールドを編集可能な状態にしなさい」という一連の流れが完成しました。

16.変更を保存後、Xcodeウインドウ上部にある、ビルドして進行を押します。しばらくするとシミュレーターが起動します。

上のテキストフィールド上でマウスをクリックして、キーボードが開いたら右下の「Next」(日本語キーボードが表示されている場合だと「次へ」)を押してみてください。 下のテキストフィールドにカーソルが移ります。同じようなことを下のテキストフィールドでも行うと、 これとは逆に下のテキストフィールドから上のテキストフィールドへ移動させることも出来ます。 使ってもいないtextField1を宣言したのは後からそれを追加する場合にわかりやすくするためです。


おまけ

全くの余計な話ですが、私の場合、deallocはテンプレートから作ったままの状態(ファイルの一番下の部分に配置)にはせず、一番上の@synthesize直後に移動させてしまうことが多いです。 そうしておくと後からメンバオブジェクトを追加した場合に、@synthesizeの追加とdeallocへのreleaseの追加が一度に行えて楽だからです。 同様に、ヘッダの@interfaceが閉じる中括弧をはさんで宣言と@propertyを上下対称に配置します。 文章だけだとわかりにくいので上の例の場合に、もともとtextField1しかないところに、後からtextField2を追加したと仮定してコードを載せてみます。

@interface MoveFieldViewController : UIViewController {
    UITextField *textField1;
    UITextField *textField2;
}
@property (nonatomic. ratain) IBOutlet UITextField *textField2;
@property (nonatomic. ratain) IBOutlet UITextField *textField1;

- (IBAction)pushNextButtonAtTextField1:(id)sender;

@end

この配置の利点は、他のヘッダファイルでも同様の変更が必要でコピー&ペーストする時に、textField2の宣言と@propertyを一回の貼り付けだけで追加できることです。

@implementation MoveFieldViewController
@synthesize textField1;
@synthesize textField2;

- (void)dealloc {
    [textField2 release];
    [textField1 release];
    [super dealloc];
}

こちらも同じように、「@synthesize textField2;~[textField2 release];の4行をコピーすることで、 他のメソッドファイルに一回で@synthesizeとdealloc内にあるtextField2のreleaseが追加できます。 人によっては見にくいと感じるかも知れませんが、慣れるとけっこう便利ですよ。


前へ次へ
Copyright© 2009 Konton All rights reserved. - このサイトについて - サイトマップ

Valid XHTML 1.1 正当なCSSです!