Combining 2 answers found here I was able to find a workaround for me, but it was necessary to subclass NSTextField, NSTextFieldCell and NSTextView.
Swift 5
1.
Subclass NSTextView, this is where the actual paste is intercepted and can the content be replaced.
final class TextView: NSTextView {
override func paste(_ sender: Any?) {
var content = NSPasteboard.general.string(forType: .string) ?? ""
// modify content
NSPasteboard.general.clearContents()
NSPasteboard.general.setString(content, forType: .string)
super.paste(sender)
}
}
2.
Subclass NSTextFieldCell and override fieldEditorFor with your own NSTextView. Important to set to true the property isFieldEditor of the NSTextView.
final class TextFieldCell: NSTextFieldCell {
private let textView = TextView()
required init(coder: NSCoder) {
super.init(coder: coder)
}
override init(textCell: String) {
super.init(textCell: textCell)
textView.isFieldEditor = true
}
override func fieldEditor(for: NSView) -> NSTextView? {
textView
}
}
3.
Subclass NSTextField and assign to the static property cellClass your own NSTextFieldCell. This last step could be avoided if you simply assign your own NSTextFieldCell to all NSTextField, i.e. NSTextField.cellClass = yourCellClass
final class TextField: NSTextField {
required init?(coder: NSCoder) {
nil
}
init() {
TextField.cellClass = TextFieldCell.self
super.init(frame: .zero)
}
}