swiftmacosnstextfieldnstrackingarea

Swift NSTextField text disappears


This questions MIGHT exist on a 6 year old post in objective-c. I haven't found a recent answer or question that works, or one that is written in Swift.

I'm using storyboards and I have subclassed NSTextField. For some reason when I click into the field, the placeholder shows and when I enter text and click out, the text disappears. The text is actually there, because when I click back in, the entered text persists. It seems that it's some type of rendering issue that a layer is covering up the text value? Very strange. I'm using NSTrackingArea and also adding CALayer.

Here's a screenshot of what happens: enter image description here

Here's my code:

class NowTextField: NSTextField {

    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)

        // required nonsense
        let textFieldLayer = CALayer()
        let textFieldRect = NSRect(x: 0, y: 0, width: 120, height: 32)
        let textFieldTrackingArea = NSTrackingArea.init(rect: textFieldRect, options: [NSTrackingAreaOptions.activeInActiveApp, NSTrackingAreaOptions.mouseEnteredAndExited], owner: self, userInfo: nil)
        self.wantsLayer = true
        self.layer = textFieldLayer
        self.addTrackingArea(textFieldTrackingArea)

        // styling
        self.textColor = NSColor.darkGray
        self.layer?.cornerRadius = 4
        self.layer?.backgroundColor = NSColor.white.cgColor
        self.layer?.borderColor = NSColor.lightGray.cgColor
        self.layer?.borderWidth = 2
        self.drawsBackground = false
    }

    override func mouseEntered(with event: NSEvent) {
        self.textColor = NSColor.darkGray
        self.layer?.cornerRadius = 4
        self.layer?.backgroundColor = NSColor.white.cgColor
        self.layer?.borderColor = NSColor.highlightBlue.cgColor
        self.layer?.borderWidth = 2
        self.drawsBackground = false
    }

    override func mouseExited(with event: NSEvent) {
        self.textColor = NSColor.darkGray
        self.layer?.cornerRadius = 4
        self.layer?.backgroundColor = NSColor.white.cgColor
        self.layer?.borderColor = NSColor.lightGray.cgColor
        self.layer?.borderWidth = 2
        self.drawsBackground = false
    }
}

Solution

  • I found the answer. I deleted let textFieldLayer = CALayer() as well as self.layer = textFieldLayer as these seemed to be adding an unnecessary layer on top of the text field. Here's my full code for the working version:

    class NowTextField: NSTextField {
    
    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)
    
        // required nonsense
        let textFieldRect = NSRect(x: 0, y: 0, width: 120, height: 32)
        let textFieldTrackingArea = NSTrackingArea.init(rect: textFieldRect, options: [NSTrackingAreaOptions.activeInActiveApp, NSTrackingAreaOptions.mouseEnteredAndExited], owner: self, userInfo: nil)
        self.wantsLayer = true
        self.addTrackingArea(textFieldTrackingArea)
    
        // styling
        self.textColor = NSColor.darkGray
        self.layer?.cornerRadius = 4
        self.layer?.backgroundColor = NSColor.white.cgColor
        self.layer?.borderColor = NSColor.lightGray.cgColor
        self.layer?.borderWidth = 2
        self.drawsBackground = false
    }
    
    override func mouseEntered(with event: NSEvent) {
        self.textColor = NSColor.darkGray
        self.layer?.cornerRadius = 4
        self.layer?.backgroundColor = NSColor.white.cgColor
        self.layer?.borderColor = NSColor.highlightBlue.cgColor
        self.layer?.borderWidth = 2
        self.drawsBackground = false
    }
    
    override func mouseExited(with event: NSEvent) {
        self.textColor = NSColor.darkGray
        self.layer?.cornerRadius = 4
        self.layer?.backgroundColor = NSColor.white.cgColor
        self.layer?.borderColor = NSColor.lightGray.cgColor
        self.layer?.borderWidth = 2
        self.drawsBackground = false
    }
    

    }