omgtheykilledkenny omgtheykilledkenny - 3 months ago 28
Swift Question

recognizing key event in entire window

i am working on a transliteration app that gets some text from an NSTextView and transliterate it and puts it in another NSTextView,
what i want to do is, as the user is typing the sentence when he types a word and presses space i want the space key to trigger an action which i specify to break the sentence into an array of individual words.
in order to do that i have tried overriding the keyDown function in the viewController class:

override func keyDown(theEvent: NSEvent) {
if (theEvent.keyCode == 49){
print("pressed space")
}
}


which does not work , it works when i subclass NSTextView class and override keyDown function in it but my textView stops inputing text.
how can i set a key event for space key that works ? any other suggestion for breaking a sentence into word array by pressing space?

thanks

Answer

Step 1 is to set your View Controller to be a delegate of NSTextField. If you use nibs or storyboard it will look like this:

enter image description here

Basically ctrl drag to view controller and set delegate.

Then you can react on text changed in your view controller:

import Cocoa

class ViewController: NSViewController {


override func controlTextDidChange(obj: NSNotification) {

    guard let textField = obj.object as? NSTextField else { return }

    if textField.stringValue.characters.last == " " {
        print(textField.stringValue.componentsSeparatedByString(" "))
    }

}
}

It will print out array of words which were separated by space:

["a", ""]

["a", "boy", ""]

["a", "boy", "came", ""]

["a", "boy", "came", "to", ""]

["a", "boy", "came", "to", "school", ""]

You may need to remove last item from the array:

     override func controlTextDidChange(obj: NSNotification) {

    guard let textField = obj.object as? NSTextField else { return }

    if textField.stringValue.characters.last == " " {
        print(textField.stringValue.componentsSeparatedByString(" ").filter { $0 != "" })
    }

}

For NSTextView the logic is similar. Ctrl drag from text view to set view controller as delegate: enter image description here

Then use the following code:

  func textDidChange(obj: NSNotification) {

    guard let textView = obj.object as? NSTextView else { return }
    guard let stringValue = textView.textContainer?.textView?.string else { return }

    if stringValue.characters.last == " " {
        print(stringValue.componentsSeparatedByString(" ").filter { $0 != "" })
    }

}

It will work fine:

enter image description here

Comments