Show a fat iOS-Style Insertion Point in NSTextView

I have no clue why my previous attempts at customizing drawInsertionPoint(in:color:turnedOn:) always produced visual glitches. I really tried a lot of different ways.

But it turns out you don’t have to do that much, really:

class MyTextView: NSTextView {
    var caretSize: CGFloat = 4

    open override func drawInsertionPoint(in rect: NSRect, color: NSColor, turnedOn flag: Bool) {
        var rect = rect
        rect.size.width = caretSize
        super.drawInsertionPoint(in: rect, color: color, turnedOn: flag)
    }

    open override func setNeedsDisplay(_ rect: NSRect, avoidAdditionalLayout flag: Bool) {
        var rect = rect
        let width = rect.size.width + insertionPointWidth - 1
        rect.size.width = max(rect.size.width, width) // Updated 2022-08-29
        super.setNeedsDisplay(rect, avoidAdditionalLayout: flag)
    }
}

Adapted to Swift from a Gist by koenbok.

That’s all it takes. Marvelous!

Update: So it turns out that the drawing works just fine in a test project, but I end up with 1px-wide insertion points/carets/I-beams when I click with the mouse or press up/down arrow keys. Left and right work fine. I wonder what’s wrong with this.

Update 2022-08-29: I should’ve added more context to my last update because I eventually shipped more or less this exact approach without trouble, though I’m limiting rect.size.width in production. Maybe that was it? Users of The Archive enjoy fat carets for more than 4 years now without trouble. – Note that Ryan posted a link to a Gist with similar code in the comments.