Connect to ViewController from AppDelegate (Swift)

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

I implemented IBAction in AppDelegate.swift to handle when users select "Open ..." from the "File" menu. If the selected file is a valid image file, I create NSImage, which I then want to display in the 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 see no way to connect to the ViewController from AppDelegate. I only managed to find offers that I should look at self.window! in AppDelegate, but in AppDelegate there is no such thing as a window.

Thank you Michael Knudsen

+7
xcode cocoa swift macos
source share
4 answers

It seems that AppDelegate can only connect to objects within the application in the storyboard. If you want to get a ViewController, create it from the storyboard.

Example:

 @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 } } } 
+11
source share

I was stuck trying to do the same thing recently, and I managed to refresh my view by creating @IBAction in my ViewController and dragging control to my first app responder (above the menu in my storyboard).

Here is the question that called me out of the forest: Xcode application menu items

And thanks to Bluedome for the offer to connect him to the action of the first responder.

+1
source share

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

 override var acceptsFirstResponder: Bool { return true } func openFile(sender: NSMenuItem) { print("In view controller") } 

and it worked without any changes to AppDelegate. Most menus are already connected to the first responder, so just add the name of the corresponding function to the view controller.

See the commentary and this document on the Basics of Event Processing for more information.

0
source share

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

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

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

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

This is useful for a simple one-window application with one ViewController.

0
source share

All Articles