如何从子类NSTextField设置NSButton.isEnabled

时间:2018-06-22 05:42:59

标签: swift macos becomefirstresponder

我对Swift MacOS编程非常陌生,并且通过编写小型测试应用程序来学习。

此应用程序的目的是在第二个文本字段具有焦点时启用按钮,而在未聚焦时禁用按钮。

我发现通过子类化NSTextField可以覆盖becomeFirstResponder(),但是不知道如何从子类中设置要禁用的按钮。

ViewController:

class ViewController: NSViewController {

    @IBOutlet public weak var pushButton: NSButton!

    @IBOutlet weak var textField3: NSTextField!
    @IBOutlet weak var textField2: GSTextField!
    @IBOutlet weak var textField1: NSTextField!


    override func viewDidLoad() {
        super.viewDidLoad()

        textField2.delegate = self

    // Do any additional setup after loading the view.
    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }

    func chgButton(onoff: Bool){
        pushButton.isEnabled = onoff
    }

}

// When the field completes editing make the pushbutton disabled.
extension ViewController: NSTextFieldDelegate {
    override func controlTextDidEndEditing(_ obj: Notification) {
        print("did end")
        chgButton(onoff: false)

    }
}

GSTextField.Swift

class GSTextField: NSTextField {

    override func becomeFirstResponder() -> Bool {
        print("GSTextField Firstresponder")
 ////*** I need to set the button to be enabled here
        return super.becomeFirstResponder()
    }
 }   

1 个答案:

答案 0 :(得分:0)

您的NSTextField子类需要能够与按钮通信。最简单的方法是将对按钮的引用传递到您的文本字段,然后从那里更新按钮。

像这样更新您的ViewController:

override func viewDidLoad() {
    super.viewDidLoad()

    textField2.delegate = self
    textField2.pushButton = pushButton

    // Do any additional setup after loading the view.
}

您的GSTextField如下:

class GSTextField: NSTextField {

    weak var pushButton: NSButton?

    override func becomeFirstResponder() -> Bool {
        print("GSTextField Firstresponder")
        pushButton?.isEnabled = true
        return super.becomeFirstResponder()
    }

    override func resignFirstResponder() -> Bool {
        pushButton?.isEnabled = false
        return super.resignFirstResponder()
    }
}

应该注意的是,尽管在这个玩具示例中可以很好地工作,但这不是此问题的次佳解决方案,因为它紧密地结合了pushButton和GSTextField。更好的解决方案是使用委托将焦点更改传达给ViewController,然后让ViewController处理更新。

您的GSTextField看起来像这样:

protocol FocusObservable: class {
    func didGainFocus(sender: Any)
    func didLoseFocus(sender: Any)
}

class GSTextField: NSTextField {

    weak var focusDelegate: FocusObservable?

    override func becomeFirstResponder() -> Bool {
        print("GSTextField Firstresponder")
        focusDelegate?.didGainFocus(sender: self)
        return super.becomeFirstResponder()
    }

    override func resignFirstResponder() -> Bool {
        focusDelegate?.didLoseFocus(sender: self)
        return super.resignFirstResponder()
    }
}

然后将协议一致性添加到ViewController:

extension ViewController: FocusObservable {
    func didGainFocus(sender: Any) {
        pushButton.isEnabled = true
    }

    func didLoseFocus(sender: Any) {
        pushButton.isEnabled = false
    }
}

并设置文本字段的focusDelegate:

override func viewDidLoad() {
    super.viewDidLoad()

    textField2.delegate = self
    textField2.focusDelegate = self
    // Do any additional setup after loading the view.
}