再利用可能なUIパーツをInterface Builderを使って簡単につくる方法を調べてみたのですが、基本的な事項の割にはドキュメントやサンプルが見つけられずに苦労してしまったのでまとめておきます。(Appleのサンプルでは一部をIBで、一部をコードで行うものはありましたが、できることなら極力IBを使うようにしたいところです。)
まず、メインのViewControllerのXibファイルにViewControllerを追加してパーツを読み込む方法を考えたのですが、『iOS View Controllerプログラミングガイド』によると、この方法はよろしくないようです。
ViewControllerとそのビュー階層のビューを1対1で対応させることは、設計上重要な検討項目です。同じ ビュー階層の別々の部分を管理するために、複数のカスタムView Controllerを使用するべきではあり ません。同様に、複数の画面に相当するコンテンツを管理するために、単独のカスタムViewController を使用するべきではありません。
なるほど。さらに、今回の問題のヒントになる次のような記述がありました。
注: 1つのビュー階層を複数の下位階層に分割して、下位階層を別々に管理する場合は、ViewControllerオブジェクトではなく、汎用のControllerオブジェクト(NSObjectから派生させたカスタムオブジェクト)を使用します。そして、1つのView Controllerを使用して、それらの汎用Controllerオブジェクトを管理します。
なるほど。結局、これ以上詳しい説明は見つけられなかったので、これをヒントに試行錯誤しながら次の方法を使うことにしました。
今回は、私が作っている体重管理のiPhoneアプリ『シンプル・ダイエット』の入力画面の液晶ディスプレイ部分をパーツ化して、同じViewを使って体重と体脂肪率を表示するためのそれぞれのViewをつくります。

1. パーツ用のUIView継承クラスと、Xibファイルを作成
まず、パーツ(ここでは液晶ディスプレイ部分)を表すクラスを作成します。
XCodeで、右クリック→Add→New File...でCocoaTouch Classの中にあるObjective-C Classを選び、UIViewのサブクラスとして追加します。さらに、右クリック→Add→New File...で、User Interfaceの中からView XIBを選んでXibファイルを追加します。
こんな感じ。

2. InterfaceBuilderでXibファイルを編集
次に、InterfaceBuilderでXibファイルを編集します。

Document Windowはこんな感じです。

ポイントは、File's Ownerに先ほど作成したクラス(ここではLCDViewクラス)を指定し、UIViewを一番上のView階層として、その下にいろいろなパーツを入れていく点です。
3. UIView継承クラスのヘッダファイルにIBOutletを追加
先ほど作成したクラスのヘッダファイル(ここではLCDView.h)にそれぞれのパーツに対応するIBOutletを追加していきます。追加したら、InterfaceBuilderで、File's OwnerのViewConnectionを各パーツにつなげていきます。一番上のView階層にしたUIViewにもIBOutletをつけてFile's Ownerとつなげておくのを忘れないように。今回の例ではcontentViewという名前をつけています。
4. awakeFromNibでXibファイルを読み込むように実装ファイルを編集
さらに、実装ファイル(ここではLCDView.m)のawakeFromNibメソッドに次の2行を書きます。
- (void)awakeFromNib {
[[NSBundle mainBundle] loadNibNamed:@"LCDView" owner:self options:nil];
[self addSubview:contentView];
}
このメソッドは、メインのViewControllerからこのクラスが読み込まれたときに呼ばれて、さらにここで作成したパーツのXibを読み込み、その内容をまるごとサブビューとして追加しています。(今回作成したパーツをメインのViewControllerのXibに追加しないでコードで作成する場合は、上の2行はinitメソッドなどに書くことになります。今回は極力IBを使ってUIの作成に関するコードを書かずに済ませることに執念を燃やしています。)
NSBundleのloadNibNamed:owner:options:メソッドは、UIKitの追加メソッドです。NSArrayを返してきますが、これを呼ぶだけでXibファイルを読み込んでくれるので、戻り値は気にしないで大丈夫です。
あとは、このビューパーツに必要な機能を適宜実装していきます。(UIView継承クラスにコントローラ的役割を持たせることになってしまいますが、他によい方法がないので、固いことは考えないことにします。)
5. メインのViewControllerのXibに、今作成したUIView継承クラスを追加
画面を司るメインのViewControllerのXibファイルをInterface Builderで開き、今作成したUIView継承クラスを追加します。InterfaceBuilderのLibraryから一度UIViewを追加して、View IdentityのClassを変更します。(ここではLCDViewに変更)
上でこのパーツのコントローラ的役割のクラスをUIView継承クラスにしたのは、ここで階層や位置やサイズなどのViewの属性を指定できるようにするためです。

6. メインのViewControllerにIBOutletを追加して接続
最後に、メインのViewControllerのヘッダファイルにIBOutletを追加して、今回作成したパーツを接続します。
以上で、メインのViewControllerからViewパーツを使い回して複数作成することができました。これで他のアプリでも使えるViewパーツをたくさんつくって蓄積していけば、新規開発がどんどん楽になると思います。
今回試行錯誤でみつけたこれが正しい方法かどうかはよくわかりません。もっとよいやり方がありましたら教えて下さい。m(_ _)m





