How to live check a NSTextField - Swift OS X
Asked Answered
U

6

6

I am currently making an OS X application written in Swift. What I want to do is when the user enters text in a NSTextField, I want to run a function that checks the value and adds it to a Label. How would I do this in swift?

Uredium answered 9/1, 2016 at 14:15 Comment(0)
P
9
  1. Conforms ViewController to protocol NSTextDelegate.
  2. Assign ViewController as Delegate for TextField.
  3. Implement controlTextDidChange method.

    import Cocoa
    
    @NSApplicationMain
    class AppDelegate: NSObject, NSApplicationDelegate, NSTextFieldDelegate {
    
        @IBOutlet weak var window: NSWindow!
        @IBOutlet weak var textField: NSTextField!
        @IBOutlet weak var label: NSTextField!
    
    
        func applicationDidFinishLaunching(aNotification: NSNotification)
        {
            textField.delegate = self
        }
    
        override func controlTextDidChange(notification: NSNotification)
        {
            let object = notification.object as! NSTextField
            self.label.stringValue = object.stringValue
        }
    
        func applicationWillTerminate(aNotification: NSNotification) {
            // Insert code here to tear down your application
        }
    }
    

in ViewController:

import Cocoa

class ViewController: NSViewController, NSTextDelegate {

   @IBOutlet weak var label: NSTextField!
   @IBOutlet weak var label2: NSTextField!
   @IBOutlet weak var textField: NSTextField!
   @IBOutlet weak var textField2: NSTextField!

   override func viewDidLoad() {
      super.viewDidLoad()
   }

   override func controlTextDidChange(notification: NSNotification) {
      if let txtFld = notification.object as? NSTextField {
         switch txtFld.tag {
         case 201:
            self.label.stringValue = txtFld.stringValue
         case 202:
            self.label2.stringValue = txtFld.stringValue
         default:
            break
         }
      }
   }
}
Pitchford answered 11/1, 2016 at 7:42 Comment(6)
Thanks for the code. Will try later. How would I detect the label that was edited (I may have 2 at one point)Uredium
Use Tags, that allow you to identify particular controls. Tag values set in Interface BuilderPitchford
The code needs to inherit from NSTextFieldDelegate and not NSTextDelegate. You also need to set the text fields delegate to self.Uredium
You just create a methods in the AppDelegate, and I offered to do it in the ViewControllerPitchford
ViewController wasn't in the edits before which is why I couldn't do it.Uredium
I had to add NSTextFieldDelegate in ViewController, in order to receive controlTextDidChange notifications.Plano
T
4

swift 5 xcode 10

//TODO: move oin a better place?
extension NSTextField{ func controlTextDidChange(obj: NSNotification){} }


    class TracksController:NSViewController,
        NSTextFieldDelegate
    {
...
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        //Search bar:
        self.searchBar.delegate = self

        NotificationCenter.default.addObserver(self,
                                               selector: #selector(controlTextDidChange(_:)),
                                               name: NSTextView.didChangeSelectionNotification,
                                               object: nil)

    }

//MARK: NSTextFieldDelegate

func controlTextDidChange(_ obj: Notification)
{
    guard let object = obj.object as? NSTextView else{
        return
    }


    let delegate = object.delegate
    guard  let searchField = delegate as? NSSearchField else {
        return
    }

    let text = searchField.stringValue
    print(text)

}
Twitch answered 5/6, 2019 at 17:53 Comment(0)
T
2

I know it’s been answered some while ago but I did eventually find this solution for macOS in Swift 3 (it doesn’t work for Swift 4 unfortunately) which notifies when a textfield is clicked inside and for each key stroke.

Add this delegate to your class:-

NSTextFieldDelegate

In viewDidLoad()

NotificationCenter.default.addObserver(self, selector: #selector(textDidChange(_:)), name: Notification.Name.NSTextViewDidChangeSelection, object: nil)

Then add this function:-

    func textDidChange(_ notification: Notification) {
        print("Its come here textDidChange")
        guard (notification.object as? NSTextView) != nil else { return }
        let numberOfCharatersInTextfield: Int = textFieldCell.accessibilityNumberOfCharacters()
        print("numberOfCharatersInTextfield = \(numberOfCharatersInTextfield)")
}

Hope this helps others.

Theft answered 18/4, 2018 at 9:22 Comment(0)
F
1

The answers above dont work for swift 4 so,

Solution for Swift 4

The process is mostly the same but you just have to extend some functionality to the NSTextfield Class. The reason we have to do this is that the delegate protocol methods like controlTextDidChange: actually don't exist at all because of the old design of objective-c code that doesn't map well to swift. The NSTextFieldDelegate in objective-c is an informal protocol which is the same thing as an extension in swift.

Example

extension NSTextField{ func controlTextDidChange(obj: NSNotification){} }

class SomeViewController:NSViewController,NSTextFieldDelegate {

override func controlTextDidChange(_ obj: Notification)
{
    let object = obj.object as! NSTextField
    let value = object.stringValue
    print(value)
}

For every function, you want to use from the NSTextFieldDelegate just put the method in the extension clause.

Feldstein answered 17/5, 2018 at 19:2 Comment(3)
Hi! I thought this answer was helpful. However it missed a step, remember to put "textfield.delegate = self" into your ViewController (else your textfield will not report changes to your ViewController).Weinhardt
Yes, you are correct thanks. If you wanna make the edits you can, but it kind of a given.Feldstein
@user3722523 What do you mean? Where do i mention that?Feldstein
H
0
//If you want to trim Ex: Email ID, please use the below code.

class ViewController: NSViewController {

@IBOutlet weak var emailTextField: NSTextField!

override func viewDidLoad() {
    super.viewDidLoad()
    emailTextField.delegate = self
  }
}

extension ViewController : NSTextFieldDelegate {
func controlTextDidBeginEditing(_ obj: Notification) {
    print(#function)
}

func controlTextDidEndEditing(_ obj: Notification) {
    print(#function)
}

func controlTextDidChange(_ obj: Notification) {
    print(#function)
    if let textField = obj.object as? NSTextField {
        let givenText = textField.stringValue
        
        //Here you add other types of white space
        let possibleWhiteSpace: NSArray = [" ", "\t", "\n\r", "\n","\r"]
        var string: String = givenText as String
        possibleWhiteSpace.enumerateObjects { (whiteSpace, idx, stop) -> Void in
            string = string.replacingOccurrences(of: whiteSpace as! String, with: "") as String
        }
        
        print(string)
        emailTextField.stringValue = string as String
    }
 }
}
Haven answered 30/1, 2023 at 7:15 Comment(0)
H
0
extension String {
  func removeAllTypesOfWhiteSpaces(_ inputString : String) -> String {
    //Here you add other types of white space
    let possibleWhiteSpace: NSArray = [" ","\t", "\n\r", "\n","\r"]
    var outputStr: String = inputString as String
    possibleWhiteSpace.enumerateObjects { (whiteSpace, idx, stop) -> Void in
        outputStr = outputStr.replacingOccurrences(of: whiteSpace as! String, with: "") as String
    }
    return outputStr
  }
}

extension LoginViewController : NSTextFieldDelegate {
  func controlTextDidChange(_ obj: Notification) {
    if let textField = obj.object as? NSTextField {
        let givenText = textField.stringValue
        let resultStr = givenText.removeAllTypesOfWhiteSpaces(givenText)
        textField.stringValue = resultStr as String
    }
  }
}
Haven answered 30/1, 2023 at 8:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.