要在 NSViewController 的代码中构造视图,请覆盖 loadView 并确保设置视图变量。不要调用 super 的实现,因为它会尝试从 NSViewController 的 nibName 和 nibBundle 属性加载一个 nib。
-(void)loadView
{
self.view = [[NSView alloc] init];
//Add buttons, fields, tables, whatnot
}
对于 NSWindowController,过程非常相似。您应该在 loadWindow 的实现结束时调用 windowDidLoad。此外,如果窗口为 nil,则窗口控制器不会调用 loadWindow,因此您需要在初始化期间调用它。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];
}
最后,我使用自定义 NSViewController 覆盖 setView 以在使用自定义视图时设置 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;
}