xcode 从 AppDelegate (Swift) 连接到 ViewController

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27484552/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 06:21:57  来源:igfitidea点击:

Connect to ViewController from AppDelegate (Swift)

xcodemacoscocoaswift

提问by Michael Knudsen

I have created a new OS X Cocoa Application using the standard Xcode Swift template (using StoryBoards).

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

I have implemented an IBAction in AppDelegate.swift to handle when the users selects "Open..." from the "File" menu. If the chosen file is a valid image file, I create an NSImage which I then want to display in the view of ViewController.

我在 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
            }
        }
    }

However, I don't see any way to connect to ViewController from AppDelegate. I have only managed to find suggestions that I should look at self.window! in AppDelegate, but there is no such thing as a window in AppDelegate.

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

Thanks, Michael Knudsen

谢谢,迈克尔·克努森

回答by bluedome

It seems that AppDelegate can connect to objects only within Application Scene in a storyboard. If you want to get a ViewController, instantiate it from a storyboard.

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

sample:

样本:

@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
        }
    }
}

回答by John Pavley

You can access the mainWinow property and the contentViewController property to create a reference to your custom ViewController class. This is similar to the iOS rootViewController property.

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

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

Now you can use this reference to access IBOutlets on your main storyboard from your AppDelegate.

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

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

This is good for a simple app with one Window with one ViewController.

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

回答by Subcreation

I was stuck trying to do this same thing recently and managed to get the event I needed to update my view by creating the @IBAction in my ViewController and control dragging to my Application's First Responder (above the menu in my storyboard view).

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

Here's the question that got me out of the woods: Application Menu Items Xcode

这是让我摆脱困境的问题: 应用程序菜单项 Xcode

And thanks to Bluedome for the suggestion to connect it to First Responder's action.

并感谢 Bluedome 建议将其与急救人员的行动联系起来。

回答by roborom

If you control-drag from the menu to the first responder (red cube above menu) and picked an existing action, then you can "responder chain" to your view controller. In my case I attached Open to openFile and then in my view controller I added the following

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

override var acceptsFirstResponder: Bool {
    return true
}

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

and it worked without any changes in AppDelegate. Most of the menus are already hooked up to first responder so just add the matching function name in your view controller.

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

See this commentand this document on Event Handling Basicsfor more info.

有关详细信息,请参阅有关事件处理基础知识的评论和此文档。

回答by regina_fallangi

In Swift 5 and accessing new windows array:

在 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
    }
}