如何在NSTabView中设置初始视图?

时间:2013-06-20 13:06:37

标签: cocoa nstabview

我已经查看了其他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];
}

1 个答案:

答案 0 :(得分:2)

    NSViewController *newController = nil;
    newController = [[FirstViewController alloc]
                     initWithNibName:@"FirstViewController" bundle:nil];

此声明和声明可以合并到一个声明初始化器中。

initwindowDidLoad方法中执行此操作没有意义;你创建了两个独立的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中。您可以在窗口控制器的笔尖中创建所有VC。不要忘记设置它们的类名(如果你有它们的NSVC子类)和nib名称。
  • 在笔尖中创建的选项卡视图将至少包含一个选项卡视图项。我建议您在那里创建所有项目,并在运行时简单地替换他们的视图(使用VC的视图)。
  • 您应该使用windowDidLoad中的VC视图替换标签视图的项目。确保窗口未设置为最初可见;您只想在填充至少第一个标签视图项后才能显示它。

关于在笔尖中创建的选项卡视图的一个注释:最初可见的项目(选项卡)是您在笔尖中可见的项目(选项卡)。在保存之前,请确保将标签视图切换回第一个标签页。