如何在OSX Mavericks上呈现ViewControllerAsSheet?

时间:2015-06-22 12:02:06

标签: macos swift cocoa osx-mavericks nsviewcontroller

这是一个很长的故事,但要缩短它;我的第一个OSX应用程序是在Swift中使用故事板编写的(在Yosemite上)直到我发现我的(已完成)应用程序不会在Mavericks上运行。我需要在Mavericks上运行,所以我用NIB替换了故事板。

我的问题在于segues;我正在使用'表格类型' segue在主视图控制器上显示工作表中的其他视图控制器。对NSViewController的presentViewControllerAsSheet方法的调用是一个很好的替代,因为它看起来一样,但是这个API是在Yosemite中引入的 - 所以我需要弄清楚如何为Mavericks做这个。

在主视图中按钮的操作中,我尝试过使用这样的beginSheet:

secondViewController = SecondViewController(nibName: "SecondViewController", bundle: nil)
self.view.window?.beginSheet(secondViewController!view.window!, completionHandler: nil)

但是第二个视图控制器的窗口在运行时为空。我已经尝试将新视图控制器作为子视图添加到应用程序窗口,但这是一个无法识别的选择器:

NSApplication.sharedApplication().windows[0].addSubView(secondViewController!.view)

我搜索高低搜索有关如何显示工作表的说明,我能找到的是:Can a view controller own a sheet?但我很抱歉承认我不明白回答。有人可以帮我一些工作代码吗?我开始担心我会尝试做一些与众不同的事情,但在优胜美地看起来不错,所以人们在优胜美地被释放之前是如何做到这一点的?

修改 我仍然无法解决问题,因此我整理了一个小应用程序,显示了我遇到的问题。

在AppDelegate.swift中:

class AppDelegate: NSObject, NSApplicationDelegate {
    @IBOutlet weak var window: NSWindow!
    var mainViewController: FirstView!   
    func applicationDidFinishLaunching(aNotification: NSNotification) {
        mainViewController = FirstView(nibName:"FirstView", bundle: nil)
        window.contentView = mainViewController.view
        mainViewController.view.frame = (window.contentView as! NSView).bounds
    }
}

在FirstView.swift中(关联的NIB有一个'打开的工作表'按钮)

class FirstView: NSViewController {
    var secondView: SecondView?
    var secondWindow: SecondWinCon?    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    @IBAction func pressButton(sender: AnyObject) {
        secondView = SecondView(nibName: "SecondView", bundle: nil)!
// method 1 - this is the behaviour I want (but it only works on OSX 10.10)
//        presentViewControllerAsSheet(secondView!)
// method 2 - this just creates a floating window
//        self.view.addSubview(secondView!.view)
//        self.view.window?.beginSheet(secondView!.view.window!, completionHandler: nil)
// method 3 - this also creates a floating window
        secondWindow = SecondWinCon(windowNibName: "SecondWinCon")
        self.view.window?.beginSheet(secondWindow!.window!, completionHandler: nil)   
    }    
}

在SecondView.swift中(关联的NIB有一个'关闭'按钮)

class SecondView: NSViewController {   
    override func viewDidLoad() {
        super.viewDidLoad()
    }       
    @IBAction func dismissPressed(sender: AnyObject) {
        if (presentingViewController != nil) {
            presentingViewController?.dismissViewController(self)
        } else {
            self.view.window?.sheetParent?.endSheet(self.view.window!)
        }
    }
}

在SecondWinCon.swift中(关联的NIB为空)

class SecondWinCon: NSWindowController {
    var secondView: SecondView?
    override func windowDidLoad() {
        super.windowDidLoad()   
        secondView = SecondView(nibName: "SecondView", bundle: nil)!
        self.window?.contentView.addSubview(secondView!.view)
    }   
}

如果取消注释方法1,您将看到我尝试模拟的行为(记住它仅适用于OS X 10.10)。方法2或3显示第二个视图,但不显示为工作表。

2 个答案:

答案 0 :(得分:5)

我遇到了同样的问题,发现可能是与视图生命周期相关的问题。 当我在viewDidLoad中调用presentViewControllerAsSheet时,不会显示工作表,你将在控制台中得到它:

  

无法在(NSWindow)上设置(contentViewController)用户定义的检查属性:presentViewController:animator :: View''的视图不在窗口/视图层次结构中。

如果您在viewWillAppear或viewDidAppear中触发此操作,则完全没问题。

<强>更新

好的,让我们说清楚。

对于这个初始故事板,NSWindowController与视图控制器连接,将其视为根视图控制器(RootVC)。 在storyboard(SheetVC)中创建另一个所需的视图控制器作为工作表。 在RootVC的viewWillAppear或viewDidAppear中,[self presentViewControllerAsSheet:SheetVC]

表格将显示,无需其他代码。

答案 1 :(得分:1)

如果你到这里寻找解决方案,我几乎就是方法3.我错过的重要一步是关闭&#34;可见发射&#34;在NSWindowController的NIB中(它是NSWindow的一个属性)。在我的示例代码中,这是在SecondWinCon.nib中。