Fafa
Fafa

Reputation: 103

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

I'm writting a simple VAT calculator enter image description here

I would like change the aspect of TextFields, focused one as white background and the others have grey background.

Event sending for Textfields seems to be when leave focus, so as i want to change color when enter focus, i've subclass NSTextField in FATextfield. Detect which Textfield as focus is OK.

After that, i would like to have a function that changes background according to the actual focused TextField.

I don't understand in my textFieldsLookUpdate function, view is not loaded and all FATextFields are nil ...

Thanx

My FATextField class :

import Cocoa

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

My View Controller :

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)
    }
}

In Storyboard the TextFields are rightly set to FATextView

Upvotes: 0

Views: 75

Answers (2)

Fafa
Fafa

Reputation: 103

In fact, after much research, the main thing that a newbie like me should know is that NSTextField inherits from NSControl.

While exploring NSControl I found:

/* 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)

Changing the appearance of the NSTextField while editing does not require a subclass, the code below works just fine:

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
        }
    }
}

The result :

enter image description here

Above the NSTextField being edited there is another NSTextField that is not being edited. Whether pressing the Tab key on the keyboard or clicking with the mouse, everything goes as expected.

Upvotes: 0

matt
matt

Reputation: 534885

The problem is actually in the previous line:

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

So now you have created a ViewController instance — and you then call its textFieldClicked method and you throw the view controller away. Which is fine, because it was always useless. The key fact is that this is not the right view controller. You don't want to create a new view controller: you want to find the actual view controller that already exists in your interface.

Upvotes: 1

Related Questions