Swift macOS:未加载视图且视图控制器中的 IBoulet 为零

Swift macOS : view is not loaded and IBOulets are nil in View Controller

我正在写一个简单的增值税计算器

我想更改 TextFields 的外观,将一个聚焦为白色背景,其他聚焦为灰色背景。

Textfields 的事件发送似乎是在离开焦点时,所以我想在进入焦点时改变颜色,我在 FATextfield 中有 subclass NSTextField。检测哪个 Textfield 作为焦点是可以的。

在那之后,我想要一个根据实际聚焦的 TextField 改变背景的功能。

我不明白我的 textFieldsLookUpdate 函数,未加载视图并且所有 FATextFields 都是 nil ...

谢谢

我的 FATextField class :

import Cocoa

class FATextField: NSTextField {
    
    var name: String = ""
    
    override func mouseDown(with:NSEvent) {
        let viewController:ViewController = ViewController()
        viewController.textFieldClicked(FATextFieldclicked:name)
    }
    
}

我的视图控制器:

import Cocoa

class ViewController: NSViewController {
    
    var ligneBloquee: String = ""
    
    var focusedTextField: String = "none" {
        didSet {
            textFieldsLookUpdate()
        }
    }
    
    @IBOutlet weak var boutonRadioHt: NSButton!
    @IBOutlet weak var boutonRadioTva: NSButton!
    @IBOutlet weak var boutonRadioTtc: NSButton!
    @IBOutlet weak var textFieldHt21: FATextField!
    @IBOutlet weak var textFieldHt55: FATextField!
    @IBOutlet weak var textFieldHt10: FATextField!
    @IBOutlet weak var textFieldHt20: FATextField!
    @IBOutlet weak var textFieldTva21: FATextField!
    @IBOutlet weak var textFieldTva55: FATextField!
    @IBOutlet weak var textFieldTva10: FATextField!
    @IBOutlet weak var textFieldTva20: FATextField!
    @IBOutlet weak var textFieldTtc21: FATextField!
    @IBOutlet weak var textFieldTtc55: FATextField!
    @IBOutlet weak var textFieldTtc10: FATextField!
    @IBOutlet weak var textFieldTtc20: FATextField!
 
    // MARK: - Fonctions de démarrage
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    // MARK: - dans "viewDidAppear on est sur que tous les éléménets de l'interface graphique sont initialisés...
    override func viewDidAppear() {
        super.viewDidAppear()
        //textFieldHt20.window?.makeFirstResponder(textFieldHt20)
        textFieldHt21.name = "textFieldHt21"
        textFieldTva21.name = "textFieldTva21"
        textFieldTtc21.name = "textFieldTtc21"
        textFieldHt55.name = "textFieldHt55"
        textFieldTva55.name = "textFieldTva55"
        textFieldTtc55.name = "textFieldTtc55"
        textFieldHt10.name = "textFieldHt10"
        textFieldTva10.name = "textFieldTva10"
        textFieldTtc10.name = "textFieldTtc10"
        textFieldHt20.name = "textFieldHt20"
        textFieldTva20.name = "textFieldTva20"
        textFieldTtc20.name = "textFieldTtc20"
        
        if isViewLoaded {
            print ("View is loaded")
        } else {
            print ("View is not loaded")
        }
        
    }
    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }
    
    // MARK: Action des éléments graphiques
    @IBAction func boutonRadioClicked(_ sender: NSButton) {
        if sender.title == "HT" {
            ligneBloquee = "HT"
        } else if sender.title == "TVA" {
            ligneBloquee = "TVA"
        } else {
            ligneBloquee = "TTC"
        }
        print (ligneBloquee)
    }
    
    func textFieldClicked (FATextFieldclicked: String) {
        print(FATextFieldclicked)
        focusedTextField = FATextFieldclicked
    }

    private func textFieldsLookUpdate () {
        if isViewLoaded {
            print ("View is loaded")
        } else {
            print ("View is not loaded")
        }
        if textFieldHt21 == nil {
            print ("textFieldHt21 is nil")
        } else {
            print ("textFieldHt21 is not nil")
        }
    }
    
    @IBAction func FATextFieldEnter(_ sender: FATextField) {
        //print(sender.name)
    }
}

在 Storyboard 中,TextFields 被正确设置为 FATextView

其实问题出在上一行:

    let viewController:ViewController = ViewController()
    viewController.textFieldClicked(FATextFieldclicked:name)

所以现在你已经创建了一个ViewController实例——然后你调用它的textFieldClicked方法并且你抛出视图控制器离开。这很好,因为它总是没用。关键事实是,这 不是正确的视图控制器 。你不想创建一个视图控制器:你想找到 实际视图控制器已经存在于您的界面中。

其实,经过大量研究,像我这样的新手应该知道的主要是NSTextField继承自NSControl。

在探索 NSControl 时我发现:

/* The following category applies only to controls with editable text, like NSTextField.
 */
… 
open func currentEditor() -> NSText?
…
optional func controlTextDidBeginEditing(_ obj: Notification)
optional func controlTextDidEndEditing(_ obj: Notification)

编辑时更改 NSTextField 的外观不需要子类,下面的代码工作得很好:

class ViewController: NSViewController, NSTextFieldDelegate {
    
    @IBOutlet weak var textField1: NSTextField!
    @IBOutlet weak var textField2: NSTextField!
    @IBOutlet weak var label1: NSTextField!
    @IBOutlet weak var label2: NSTextField!
    
    var listOfTextfields: [NSTextField] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        textField1.delegate = self
        textField2.delegate = self
        textField1.isBezeled = false
        textField2.isBezeled = false
        listOfTextfields = [textField1, textField2]
        textField1.window?.makeFirstResponder(textField1)
        textField1.backgroundColor = NSColor.textBackgroundColor
        whichElementAsFocus()
    }
    
    override var representedObject: Any? {
        didSet {
        }
    }
    
    // Function  qui détermine quel élément à le focus
    func whichElementAsFocus() {
        for case let textField as NSTextField in self.view.subviews {
            if textField.currentEditor() != nil {
                textField.backgroundColor = NSColor.textBackgroundColor
            } else {
                textField.backgroundColor = NSColor.windowBackgroundColor
            }
        }
    }
    
    // Fonction qui se produit lorsque l'on débute la saisie
    func controlTextDidBeginEditing(_ obj: Notification) {
        whichElementAsFocus()
    }
    
    // Fonction qui se produit à chaque fois que l'on saisi un caractère
    func controlTextDidChange(_ notification: Notification) {
        /*
         if let textField = notification.object as? NSTextField {
         //print(textField.name)
         //ICI fonction de mise à jour des contenus des autres textfield
         }
         */
    }
    
    // Fonction qui se produit quand on sort d'un textfield
    func controlTextDidEndEditing(_ notification: Notification) {
        if let textField = notification.object as? NSTextField {
            textField.backgroundColor = NSColor.windowBackgroundColor
        }
    }
}

结果:

在正在编辑的 NSTextField 上方有另一个未编辑的 NSTextField。 无论是按键盘上的 Tab 键还是用鼠标点击,一切都如预期的那样。