zw

NSTextView and NSString differences in text rendering

If you're drawing a string in Cocoa, you may notice discrepancies between how the text is rendered in a NSTextView and how it's rendered when using the NSString (or NSAttributedString) AppKit drawing methods. This is because of they each use a different default NSTypesetterBehavior, which results in slightly different line spacings. When you draw a string using the drawing convenience methods - like [string drawAtPoint:point] - it uses NSTypesetterBehavior_10_2_WithCompatibility1. If you then place the same NSString (or NSAttributedString) into a NSTextView, it will look different because NSTextView uses NSTypesetterLatestBehavior. This isn't a huge problem unless you're rendering them right next to/on top of each other. For example, drawing a string into a NSCell in a NSTableView, then dynamically overlaying a NSTextView for selecting/editing. In that case, the text will jump around and it will look horrible.

Fortunately, after much searching, I found there is an easy solution. You need to change the typesetter behavior of the NSTextView's underlying NSLayoutManager, since I don't believe there is a way to the change the typesetter behavior of the string drawing methods.

[[textView layoutManager] setTypesetterBehavior:NSTypesetterBehavior_10_2_WithCompatibility];

That's it and your text will render exactly the same. You should also do this if you're programmatically calculating the height of a text block before drawing, or you'll get one height for the calculation, but when you draw the text, it won't fit.

1Apple's docs that mention this: http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/TextLayout/Tasks/DrawingStrings.html#//apple_ref/doc/uid/20001808-SW1