从AppDelegate(Swift)连接到ViewController

时间:2014-12-15 12:52:33

标签: xcode macos cocoa swift

我使用标准的Xcode Swift模板(使用StoryBoards)创建了一个新的OS X Cocoa应用程序。

我已经在AppDelegate.swift中实现了一个IBAction来处理用户何时从“文件”菜单中选择“打开...”。如果所选文件是有效的图像文件,我创建一个NSImage,然后我想在ViewController的视图中显示。

    @IBAction func openFile(sender: NSMenuItem) {
    var openPanel = NSOpenPanel()
    openPanel.beginWithCompletionHandler { (result :Int) -> Void in
        if result == NSFileHandlingPanelOKButton {
            if let imageURL = openPanel.URL {
                let image = NSImage(contentsOfURL: imageURL)
                // PRESENT image IN THE VIEW CONTROLLER
            }
        }
    }

但是,我没有看到任何从AppDelegate连接到ViewController的方法。我只是设法找到了我应该看看self.window的建议!在AppDelegate中,但AppDelegate中没有窗口这样的东西。

谢谢, Michael Knudsen

5 个答案:

答案 0 :(得分:13)

似乎AppDelegate只能连接到故事板中应用程序场景中的对象。如果您想获取ViewController,请从故事板中实例化它。

样品:

@IBAction func menuAction(sender: AnyObject) {
    if let storyboard = NSStoryboard(name: "Main", bundle: nil) {
        let controller = storyboard.instantiateControllerWithIdentifier("VC1") as NSViewController

        if let window = NSApplication.sharedApplication().mainWindow {
            window.contentViewController = controller // just swap
        }
    }
}

答案 1 :(得分:1)

我最近一直试图做同样的事情并设法通过在我的ViewController中创建@IBAction并控制拖动到我的应用程序的第一响应者(在菜单上方)来获取我需要更新视图的事件我的故事板视图)。

这是让我走出困境的问题: Application Menu Items Xcode

感谢Bluedome建议将其与First Responder的行动联系起来。

答案 2 :(得分:0)

如果你控制 - 从菜单拖动到第一个响应者(菜单上方的红色立方体)并选择一个现有的动作,那么你可以“响应链”到你的视图控制器。在我的情况下,我将Open附加到openFile,然后在我的视图控制器中添加了以下

override var acceptsFirstResponder: Bool {
    return true
}

func openFile(sender: NSMenuItem) {
    print("In view controller")
}

并且它在AppDelegate中没有任何更改的情况下工作。大多数菜单已经连接到第一响应者,因此只需在视图控制器中添加匹配的函数名称。

有关详细信息,请参阅此comment以及Event Handling Basics上的此文档。

答案 3 :(得分:0)

您可以访问mainWinow属性和contentViewController属性来创建对自定义ViewController类的引用。这类似于iOS rootViewController属性。

let rootViewController = NSApplication.shared().mainWindow?.windowController?.contentViewController as! ViewController

现在,您可以使用此引用从AppDelegate访问主故事板上的IBOutlets。

rootViewController.myTextView.textStorage?.mutableString.setString("Cats and dogs.")

这对于一个带有一个ViewController的Window的简单应用程序很有用。

答案 4 :(得分:0)

在Swift 5中并访问新的Windows数组:

@IBAction func menuAction(sender: AnyObject) {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let controller = storyboard.instantiateInitialViewController()
    // The windows in the array are ordered from back to front by window level;
    // thus, the last window in the array is on top of all other app windows.
    // On app launch, UIApplication.shared.windows.count == 1 anyway.
    if let window = UIApplication.shared.windows.last {
        window.rootViewController = controller
    }
}
相关问题