1

My goal is to make text selection behaviour similar to Apple Pages, MS Word and any other text processor, when NSTextView selects ONLY text glyphs and not any indents or the whole NSTextContainer size like by default NSTextView's behavior.

With that goal in mind, I subclassed NSLayoutManager and overrided func rectArray(forCharacterRange charRange: NSRange, withinSelectedCharacterRange selCharRange: NSRange, in container: NSTextContainer, rectCount: UnsafeMutablePointer<Int>) -> NSRectArray?

In my override I simply calculated new rects that bound just glyphs and rejects any indents, blank spaces etc.

Everything worked fine. But suddenly in macOS 10.11 Apple did deprecate the method I'm using. And suggested to use func enumerateEnclosingRectsForGlyphRange: withinSelectedGlyphRange: inTextContainer: usingBlock: instead.

But it seems that this new method doesn't work in a way the previous deprecated method did. It's impossible to customize enclosing rects any more. All I can do is to enumerate through rects TextKit did calculate. And now it's impossible to achieve desirable text selection behaviour because the rects are read-only. And, by the way, the new method doesn't get called at all by the TextKit. So there's no point for me to think about it.

What should I do?

Vitalii Vashchenko
  • 1,777
  • 1
  • 13
  • 23
  • File a bug report? – bhaller Jun 30 '17 at 16:01
  • It's not a bug. It was intentional. By design. They replaced an old method with the new one. It's just the functionality of the new one isn't nearly similar. – Vitalii Vashchenko Jun 30 '17 at 20:56
  • Why can't you override `enumerateEnclosingRects(forGlyphRange:withinSelectedGlyphRange:in:using:)` instead of `rectArray(forGlyphRange:withinSelectedGlyphRange:in:rectCount:)`? Or is this impossible in Swift? – Willeke Jun 30 '17 at 21:36
  • I explainded it already. enumerateEnclosingRects never gets called by the AppKit. It's just a helper method for developers to get a list of already generated rects. So, there's no point to override it. And that design decision of Apple engineers is what surprised me in the first place. – Vitalii Vashchenko Jun 30 '17 at 22:25
  • The fact that the new method does not allow the full functionality of the old method may well be a bug; you are just assuming that it isn't. The Cocoa APIs are very complex and mistakes do get made. If you see a problem with the APIs, you ought to file a bug. – bhaller Jul 01 '17 at 04:52

1 Answers1

1

While the surprise with nonequivalent method replacement remains, I was able to find a solution.

It turned out that I don't need rectArrayForCharacterRange method to do the job. I just overrided func fillBackgroundRectArray(_ rectArray: UnsafePointer<NSRect>, count rectCount: Int, forCharacterRange charRange: NSRange, color: NSColor) and put my rect calculations in there.

Everything works like a charm now!

Vitalii Vashchenko
  • 1,777
  • 1
  • 13
  • 23