Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xcode/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xcode 从AppDelegate(Swift)连接到ViewController_Xcode_Macos_Cocoa_Swift - Fatal编程技术网

Xcode 从AppDelegate(Swift)连接到ViewController

Xcode 从AppDelegate(Swift)连接到ViewController,xcode,macos,cocoa,swift,Xcode,Macos,Cocoa,Swift,我使用标准的Xcode Swift模板(使用故事板)创建了一个新的OSX Cocoa应用程序 我在AppDelegate.swift中实现了一个iAction,用于在用户从“文件”菜单中选择“打开…”时进行处理。如果选择的文件是有效的图像文件,我将创建一个NSImage,然后将其显示在ViewController的视图中 @IBAction func openFile(sender: NSMenuItem) { var openPanel = NSOpenPanel()

我使用标准的Xcode Swift模板(使用故事板)创建了一个新的OSX Cocoa应用程序

我在AppDelegate.swift中实现了一个iAction,用于在用户从“文件”菜单中选择“打开…”时进行处理。如果选择的文件是有效的图像文件,我将创建一个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中没有窗口

rootViewController.myTextView.textStorage?.mutableString.setString("Cats and dogs.")
谢谢,
Michael Knudsen似乎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
        }
    }
}

我最近一直在尝试做同样的事情,通过在我的ViewController中创建@iAction并将控件拖动到应用程序的第一响应程序(在我的故事板视图的菜单上方),我成功地获得了更新视图所需的事件

这是一个让我走出困境的问题:


感谢Bluedome建议将其连接到第一响应者的操作。

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

override var acceptsFirstResponder: Bool {
    return true
}

func openFile(sender: NSMenuItem) {
    print("In view controller")
}
而且它在AppDelegate中没有任何更改。大多数菜单已经连接到first responder,所以只需在视图控制器中添加匹配的函数名即可

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

有关详细信息,请参阅上的本文档。

您可以访问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的简单应用程序。

在Swift 5中并访问新的windows阵列:

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

谢谢正是我需要的!一旦我有了一个实例,我将如何使用它?我试着只调用一个函数,但不起作用(或者更确切地说,它需要我在方法声明中没有定义的参数)。我认为这种分离是有原因的,但由于应用程序菜单只能调用AppDelegate(菜单是UI的一部分),我不明白为什么会这样。有没有简单的方法和/或正确的方法让我的菜单项更新我的视图?使用first responder如何?在故事板中,将菜单的动作连接到您定义为@IBAction的第一响应者的动作。但是
NSViewController
不在响应程序链中,因此请将控制器设置为窗口的委托(
NSWindow
在响应程序链中)。对不起,但是使用NSApplication.shared()从AppDelegate访问根视图控制器的引用吗?听起来不对。@ElTomato shared()可能使用无括号表示法。例如,NSApplication.shared.mainWindow?.windowController?.contentViewController作为!视图控制器