Xcode 从AppDelegate(Swift)连接到ViewController
我使用标准的Xcode Swift模板(使用故事板)创建了一个新的OSX Cocoa应用程序 我在AppDelegate.swift中实现了一个iAction,用于在用户从“文件”菜单中选择“打开…”时进行处理。如果选择的文件是有效的图像文件,我将创建一个NSImage,然后将其显示在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()
@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作为!视图控制器