title: NSTextView scroll adjustment when typing at end of document
body: <p>I have a <code>NSTextView</code> with a pretty big bottom indentation. I'm using <code>textDidChange</code> delegate method to adjust some attributes in the text whenever it is changed.</p>
  <p>When typing at the edge of the screen and the end of the document, the scroll correctly gets adjusted at the bottom. However, when typing in another character after that, the scroll jumps up a bit.</p>
  <p>Looking at the call stack, I see different behavior between typing at a position which will cause the line to wrap, as compared to a normal line.</p>
  <p>When typing causes wrapping, the call stack looks like this:</p>
  <pre><code>[NSTextView adjustScroll:]
  [NSClipView _scrollTo:animateScroll:flashScrollerKnobs:]
  [NSTextView keyDown:]
  </code></pre>
  <p>Normally, <code>textDidChange:</code> is called between <code>keyDown:</code> and <code>_scrollTo:</code>, but not here.</p>
  <p>However, when typing on the line which <strong>doesn't</strong> cause a wrap, <code>textDidChange</code> is called as usual:</p>
  <pre><code>[NSTextView adjustScroll:]
  [NSClipView _scrollTo:animateScroll:flashScrollerKnobs:]
  // some attribute changes here
  [Document textDidChange:]
  [NSTextView keyDown:]
  </code></pre>
  <p>There are multiple questions on SO which state that changing attributes on <code>NSTextView</code> causes all sorts of scrolling trouble, but it's surprising that the scroll values are completely off between these two events. I'd rather have two equal results, but I'm confused what to do here. <code>_scrollTo</code> is a private method and can't be overridden, and I can't really override <code>keyDown</code> either.</p>
  <p>Is there a way to hook into the call order of scrolling and the <code>textDidChange</code> event, or to change the control flow of text and clip views?</p>
  <h2>Further investigation</h2>
  <p>To reproduce the issue, you'll have to meet at least these conditions:<br />
  • You are setting attributes in delegate method<br />
  • Text view is scaled (using <code>scaleUnitSquareToSize</code>)<br />
  • You might need to make changes to <strong>both</strong>  temporary attributes and the text view's attributed string<br />
  • Non-contiguous layout is on.</p>
  <p>Based on <a href="https://stackoverflow.com/questions/5323830/modifying-nstextstorage-attributes-causes-scroll-view-to-jump-around/8697502">this thread from 2016</a> it seems to be a non-contiguous layout bug, which is yet to be fixed. <a href="https://christiantietze.de/posts/2017/11/syntax-highlight-nstextstorage-insertion-point-change/" rel="nofollow noreferrer">A blog post from 2017</a> goes through similar issues regarding the order in which text and attributes are processed.</p>