我已经查看了其他SO问题,但看不到我需要的帮助:我在NSTabView中有一个带有NSViewControllers子类的Cocoa应用程序。
一切正常,除了 - 当我第一次运行应用程序时,Tab 0内容不显示。当我选择选项卡1,然后选项卡0,选项卡1显示,选项卡0显示确定。
我需要一些关于如何初始化标签视图的建议,因为我猜我做的事情很糟糕。
这就是我到目前为止所做的事情:
- (void)windowDidLoad
{
NSLog(@"%s", __FUNCTION__);
NSViewController *newController = nil;
newController = [[FirstViewController alloc]
initWithNibName:@"FirstViewController" bundle:nil];
NSTabViewItem *item;
[[self aTabView] selectFirstTabViewItem:newController];
newController.view.frame = aTabView.contentRect;
[item setView:firstViewController.view];
self.currentViewController = newController;
}
更新,Peter Hosey发表了很好的评论,我的工作代码如下:
- (void)windowDidLoad
{
NSLog(@"%s", __FUNCTION__);
firstViewController = [[FirstViewController alloc]
initWithNibName:@"FirstViewController" bundle:nil];
secondViewController = [[SecondViewController alloc]
initWithNibName:@"SecondViewController" bundle:nil];
thirdViewController = [[ThirdViewController alloc]
initWithNibName:@"ThirdViewController" bundle:nil];
NSTabViewItem *item;
if (firstViewController != nil) {
item = [aTabView tabViewItemAtIndex:0];
[item setView:[[self firstViewController] view]];
//[firstViewController.view.frame = aTabView.contentRect];
self.currentViewController = firstViewController;
}
}
- (BOOL)switchViewController:(NSTabView*)tabView item:(NSTabViewItem*)nextItem {
NSLog(@"%s", __FUNCTION__);
NSViewController *newController = nil;
newController.view = NO;
// assume a different identifier has been assigned to each tab view item in IB
itemIndex = [tabView indexOfTabViewItemWithIdentifier:[nextItem identifier]];
switch (itemIndex) {
case 0:
newController = firstViewController;
break;
case 1:
newController = secondViewController;
break;
case 2:
newController = thirdViewController;
break;
}
if (newController != nil) {
[nextItem setView:newController.view];
newController.view.frame = tabView.contentRect;
self.currentViewController = newController;
/*
NSLog(@"%s: myTabView.contentRect=%@ currentViewController.view.frame=%@",
__FUNCTION__, NSStringFromRect(aTabView.contentRect),
NSStringFromRect(currentViewController.view.frame));
*/
return YES;
}
else {
// report error to user here
NSLog(@"Can't load view for tab %ld", (long)itemIndex);
return NO;
}
}
- (BOOL)tabView:(NSTabView*)tabView shouldSelectTabViewItem:(NSTabViewItem*)tabViewItem {
return [self switchViewController:tabView item:tabViewItem];
}
答案 0 :(得分:2)
NSViewController *newController = nil; newController = [[FirstViewController alloc] initWithNibName:@"FirstViewController" bundle:nil];
此声明和声明可以合并到一个声明初始化器中。
在 init
和windowDidLoad
方法中执行此操作没有意义;你创建了两个独立的FirstViewControllers。
NSTabViewItem *item;
您从未创建过NSTabViewItem并将其分配给此变量。如果你期望你的selectFirstTabViewItem:
消息这样做,(1)不,那不是what that does和(2)它没有办法可能那样做,因为它不知道你的变量或者甚至你有一个。
在ARC下,此变量被隐式初始化为nil
,因此尝试在此处使用项目的所有后续消息都不会执行任何操作。如果您不使用ARC,则在尝试使用ARC时,无法初始化此变量将导致(可能是间歇性的)崩溃。
[[self aTabView] selectFirstTabViewItem:newController];
在这里传递你的闪亮的新视图控制器(其中一个)并没有按照我的想象做到。
selectFirstTabViewItem:
是一种行动方法;它的参数是消息的发送者,通常应该是控件或菜单项。当您将其设置为按钮,菜单项等的操作时,该按钮/菜单项/将是发件人。
传递视图控制器作为发送者没有意义。此外,selectFirstTabViewItem:
不会更改有关第一个选项卡视图项的任何内容(如果有的话),并且它绝对不会假设或检查其发件人是VC,如果是这样,则将项目的视图设置为VC的视图。它选择第一个选项卡视图项(使其成为当前选项卡),仅此而已。
最有可能的是,这种方法忽略了它的论点。如果要将第一个选项卡视图项的视图设置为VC的视图,则必须自己执行此操作。当然,您必须首先获取(或创建)标签视图项。
[item setView:firstViewController.view];
在ARC下,这没有任何作用;根据MRC,它可能会崩溃(见上文)。
我假设此代码来自NSWindowController子类。我进一步假设这个WC有一个笔尖。
aTabView
是一个插座,并且连接在WC的笔尖中。 aTabView
应该是使用IBOutlet
关键字声明的简单属性。不要为它实现任何自定义访问器方法;只需声明属性,将其挂钩在nib中,然后在代码中访问它。initWithWindow:
和windowDidLoad
)windowDidLoad
中的VC视图替换标签视图的项目。确保窗口未设置为最初可见;您只想在填充至少第一个标签视图项后才能显示它。关于在笔尖中创建的选项卡视图的一个注释:最初可见的项目(选项卡)是您在笔尖中可见的项目(选项卡)。在保存之前,请确保将标签视图切换回第一个标签页。