Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: Call Function when NSTextField is Edited

I try to dynamically update the text of another view with the changing user input of an NSTextField. The following approach does not work since it is for iOS. Is there something similar for osx NSTextField available?

self.equationTextField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)), for: UIControlEvents.editingChanged)
//build error: "Use of unresolved identifier 'UIControlEvents'"

Thanks!

like image 450
JFS Avatar asked Jan 08 '17 13:01

JFS


2 Answers

You will have to make use of NSControlTextEditingDelegate. Connect the NSTextField delegate to your ViewController if you are using storyboard. If you create it programmatically can just set it in code like this: textfield.delegate = self in viewDidLoad()

In the NSControlTextEditingDelegate there is a controlTextDidChange that you can make use of to get notification when text is edited.

extension ViewController: NSControlTextEditingDelegate {
    override func controlTextDidChange(_ notification: Notification) {
        if let textField = notification.object as? NSTextField {
            print(textField.stringValue)
            //do what you need here
        }
    }
}
like image 102
Zac Kwan Avatar answered Nov 08 '22 18:11

Zac Kwan


  • I found Swift 4 issue with
  • textfield.delegate = self
  • AND
  • NSControlTextEditingDelegate

  • controlTextDidChange and controlTextDidEndEditing are in NSControlTextEditingDelegate

  • this is a parent protocol of NSTextFieldDelegate protocol NSTextFieldDelegate : NSControlTextEditingDelegate
  • so VC should implement NSTextFieldDelegate not NSControlTextEditingDelegate

class  MyViewController:.... NSControlTextEditingDelegate 
textfield.delegate = self
//compile error: Cannot assign value of type 'MyViewController' to type 'NSTextFieldDelegate?'

//
class  MyViewController:.... NSTextFieldDelegate 
textfield.delegate = self  //compiles ok

Full example

//
//  MyViewController.swift
//

import Cocoa

class MyViewController: NSViewController, NSTextFieldDelegate {

    //--------------------------------------------------------------
    // MARK: -   //call in viewDidLoad
    // MARK: -
    //--------------------------------------------------------------
    func connectTONSControlTextEditingDelegate(){

        //controlTextDidChange and controlTextDidEndEditing are in NSControlTextEditingDelegate
        //this is a parent protocol of NSTextFieldDelegate
        //protocol NSTextFieldDelegate : NSControlTextEditingDelegate
        //so  implement NSTextFieldDelegate 
        //class MyViewController:.... NSTextFieldDelegate
        //then connect it here to NSTextFields

        //then override controlTextDidChange OR controlTextDidEndEditing

        self.textField0.delegate = self
        self.textField1.delegate = self

    }


    //--------------------------------------------------------------
    // MARK: -  NSControlTextEditingDelegate
    // MARK: -
    //--------------------------------------------------------------
    //called everytime you type in field
    override func controlTextDidChange(_ notification: Notification) {

        if let textField = notification.object as? NSTextField {
            if textField === textField0{
                logger.info("[controlTextDidChange][textField0]:'\(textField.stringValue)'")

            }
            else if textField === textField1{
                logger.info("[controlTextDidChange][textField1]:'\(textField.stringValue)'")

            }
            else{
                logger.error("[controlTextDidChange][UNHANDLED NSTextField]")
            }
        }
    }

    //User tapped in NSTextfields and then clicked out - text may not have changed
    //this is actually on NSObject in appkit
    //dont need both controlTextDidChange and controlTextDidEndEditing but no harm if you do
    override func controlTextDidEndEditing(_ notification: Notification){
        if let textField = notification.object as? NSTextField {

            if textField === textField0{
                logger.info("[controlTextDidEndEditing][textField0]:'\(textField.stringValue)'")

            }
            else if textField === textField1{
                logger.info("[controlTextDidEndEditing][textField1]:'\(textField.stringValue)'")

            }
            else{
                logger.error("[controlTextDidEndEditing][UNHANDLED NSTextField]")
            }
        }
    }



    //--------------------------------------------------------------
    // MARK: - NSTextFields
    // MARK: -
    //--------------------------------------------------------------
    @IBOutlet weak var textField0: NSTextField!
    @IBOutlet weak var textField1: NSTextField!

    //--------------------------------------------------------------
    // MARK: - viewDidLoad
    // MARK: -
    //--------------------------------------------------------------
    override func viewDidLoad() {
        super.viewDidLoad()

        //---------------------------------------------------------
        //setup text change delegates - see extension above
        connectTONSControlTextEditingDelegate()
        //---------------------------------------------------------
    }
}
like image 39
brian.clear Avatar answered Nov 08 '22 18:11

brian.clear