NSViewControllerのコードでビューを作成するには、loadViewをオーバーライドし、必ずビュー変数を設定してください。NSViewControllerのnibNameプロパティとnibBundleプロパティからnibを読み込もうとするため、superの実装を呼び出さないでください。
-(void)loadView
{
self.view = [[NSView alloc] init];
//Add buttons, fields, tables, whatnot
}
NSWindowControllerの場合、手順は非常に似ています。loadWindowの実装の最後にwindowDidLoadを呼び出す必要があります。また、ウィンドウがnilの場合、ウィンドウコントローラはloadWindowを呼び出さないため、init中に呼び出す必要があります。NSWindowControllerは、ペン先からロードする場合を除いて、コントローラーを作成する前にコードでウィンドウを作成することを想定しているようです。
- (id)initWithDocument:(FFDocument *)document
url:(NSURL *)url
{
self = [super init];
if (self)
{
[self loadWindow];
}
return self;
}
- (void)loadWindow
{
self.window = [[NSWindow alloc] init];
//Content view comes from a view controller
MyViewController * viewController = [[MyViewController alloc] init];
[self.window setContentView:viewController.view];
//Your viewController variable is about to go out of scope at this point. You may want to create a property in the WindowController to store it.
[self windowDidLoad];
}
いくつかのオプションの空想(10.9以前)
10.10より前は、NSViewControllersはOSXの最初のレスポンダーチェーンに含まれていませんでした。アイテムがレスポンダーチェーンに存在する場合、メニューは自動的にメニューアイテムを有効/無効にします。NSViewControllerプロパティを使用してNSViewの独自のサブクラスを作成し、コントローラーをレスポンダーチェーンに追加できるようにすることができます。
-(void)setViewController:(NSViewController *)newController
{
if (viewController)
{
NSResponder *controllerNextResponder = [viewController nextResponder];
[super setNextResponder:controllerNextResponder];
[viewController setNextResponder:nil];
}
viewController = newController;
if (newController)
{
NSResponder *ownNextResponder = [self nextResponder];
[super setNextResponder: viewController];
[viewController setNextResponder:ownNextResponder];
}
}
- (void)setNextResponder:(NSResponder *)newNextResponder
{
if (viewController)
{
[viewController setNextResponder:newNextResponder];
return;
}
[super setNextResponder:newNextResponder];
}
最後に、カスタムビューを使用するときに、setViewをオーバーライドするカスタムNSViewControllerを使用して、viewControllerプロパティを設定します。
-(void)setView:(NSView *)view
{
[super setView:view];
SEL setViewController = @selector(setViewController:);
if ([view respondsToSelector:setViewController])
{
[view performSelector:setViewController withObject:self];
}
}
- (BOOL)acceptsFirstResponder
{
return YES;
}