実行中に動的に NIb を読み込んでその中にあるウィンドウを表示させてみる。
サンプル
実行させるとこんな感じ。まずメインのウィンドウが現れる。
このウィンドウは MainMenu.xib 内にあるやつ。ここでボタンを押すと別の nibファイル SampleWindow.xib を読み込み、その中にあるウィンドウを表示する。
これだけ。
実装
SampleWindowController を用意し、これでウィンドウを管理させることにする。
@interface SampleWindowController : NSObject { IBOutlet NSWindow* sampleWindow_; } - (IBAction)showWindow:(id)sender; @end実装はこう。
@implementation SampleWindowController - (IBAction)showWindow:(id)sender { if (sampleWindow_ == nil) { NSNib* nib = [[NSNib alloc] initWithNibNamed:@"SampleWindow" bundle:nil]; BOOL result = [nib instantiateNibWithOwner:self topLevelObjects:nil]; [nib release]; if (result) { NSLog(@"success"); } else { NSLog(@"failed"); } } [sampleWindow_ makeKeyAndOrderFront:self]; } @endNibの動的ロードには、NSNib を使うのがポイント。initWithNibNamed:bundle: で初期化した後、instantiateNibWithOwner:topLevelObjects: で Nibをインスタンス化する。sampleWindow_ は SampleWindow.xib 内で File'Owner とアウトレット接続してあるので、NIbのインスタンス化が完了した時点でウィンドウへの参照が入る。最後にこれを makeKeyAndOrderFront: で表示すればいい。
SampleWIndowController 自体のインスタンス生成は MainMenu.xib に入れておいいてアプリ起動時に自動的にインスタンスを生成するようにしておく(iPhoneと違い Nib内の Top Level objects はすべて retainされる)。そして最初のウィンドウ上にある "Show Sample Window"ボタンのターゲットとしてつないでおく。これでボタンを押した時に -[SampleWindowController showWindow:] が呼ばれる。
instantiateNibWithOwner:topLevelObject:
1番目の引数は File's Owner の指定。2番目の指定は Nib上のトップレベルオブジェクトのリストが NSArrayで手に入るとドキュメントにある。
動作確認してみよう。コードを次のように書き換えてデバッグコンソールを確認してみる。
NSArray* array; BOOL result = [nib instantiateNibWithOwner:self topLevelObjects:&array]; NSLog(@"%@", array);結果はこう。
LoadNibSample[2960:a0f] ( "<nsapplication: 0x100402d80>", "<nswindow: 0x10014d3a0>" )SampleWindow.xib は下図のようだから確かにリストが手に入った。
補足
Interface Builder で NSWindow を作成すると属性として "Release When Closed" にチェックが付いている。
このチェックが付いている場合、ウィンドウをクローズすると自動的にそのインスタンスが releaseされてしまう。この為、同じインスタンスを使って開閉を繰り返したい場合にこのチェックが付いているとクラッシュしてしまう。
プログラムはシグナルを受信しました:“EXC_BAD_ACCESS”。何度も開閉する場合はこのチェックを外しておく。また "Visible At Launch" もチェックが付いているので意図しない場合はこれも外しておく。
ソースコード
GitHubからどうぞ。
LoadNibSample at 2010-11-14 from xcatsan's MacOSX-Sample-Code - GitHub
Responses
Leave a Response