osx:在 NSWindowController 和 NSViewController 之间进行委托

Posted

技术标签:

【中文标题】osx:在 NSWindowController 和 NSViewController 之间进行委托【英文标题】:osx: Delegating between a NSWindowController and a NSViewController 【发布时间】:2018-09-07 04:40:18 【问题描述】:

这是我的问题简化。我有一个工具栏,窗口中有一个按钮,视图中有一个标签。单击按钮时,我想将 label.stringValue 从“ON”变为“OFF”

这里是 WindowController:

protocol ViewControllerDelegate 
    func switchOnOff()


class WindowController: NSWindowController 
    var viewDelegate: ViewControllerDelegate?
    @IBAction func pressedButton(_ sender: Any) 
        var vc = storyboard?.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "ViewController")) as? ViewController
        vc?.switchOnOff()
        
    override func windowDidLoad() 
        super.windowDidLoad()
    

这是视图控制器:

class ViewController: NSViewController 
    @IBOutlet weak var onOffLabel: NSTextField!
    override func viewDidLoad() 
        super.viewDidLoad()
        let vc = WindowController()
        vc.viewDelegate = self    

    override var representedObject: Any? 
        didSet 
        
    


extension ViewController: ViewControllerDelegate 
func switchOnOff() 
    if (onOffLabel.stringValue == "OFF" ) 
        onOffLabel.stringValue = "ON"
     else 
        onOffLabel.stringValue = "OFF"
           

这是故事板:

当我单击按钮时出现此错误:

extension ViewController: ViewControllerDelegate 
    func switchOnOff() 
        if (onOffLabel.stringValue == "OFF" )  // Thread 1: Fatal error: Unexpectedly found nil while unwrapping 
        an Optional value
            onOffLabel.stringValue = "ON"
         else 
            onOffLabel.stringValue = "OFF"
        
    

【问题讨论】:

关于:var vc = storyboard?.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "ViewController")) as? ViewController... 相关场景是否确实名为“ViewController”? 故事板 ID = ViewController 和属性检查器中的标题 == ViewController。在哪里可以找到场景的名称? @Mitch Kroska – 听起来不错(我并没有真正使用 Storyboard,所以没有更多可添加的内容,抱歉!)。 【参考方案1】:

希望这个答案还不算晚。

委托的工作方式是告诉发件人要发送给谁。您遇到的问题是您创建了一个新的 WindowController 实例并注册为它的接收者。问题是WindowController 的新实例不是发送按钮单击操作的实例。

要使其工作,您必须将您的ViewController 注册到WindowController 的唯一实例。

而不是做

let vc = WindowController()
vc.viewDelegate = self

您需要找到实际的 Window Controller 实例并注册到该实例。把上面的代码改成:

(self.view.window?.windowController as! WindowController).delegate = self

一切都应该完美无缺。

【讨论】:

以上是关于osx:在 NSWindowController 和 NSViewController 之间进行委托的主要内容,如果未能解决你的问题,请参考以下文章

如何通过按 ESC 键关闭窗口(NSWindowController)?

来自 NSWindowController Cocoa 的自定义视图

NSManagedObjectContext 传递给 NSWindowController 变为 nil

Interface builder中的NSWindowController对象链接

Swift 中的 NSWindowController。使用 Nib 进行子类化和初始化

使用 Swift 在 OS X 应用程序中打开新窗口