NSTextView subclass not displaying text in Sonoma

This is a tricky one. I have a shipping product which, when compiled under Xcode 14.3.1 works as expected on Sonoma.

If the same project is recompiled with Xcode 15, the subclass of NSTextView will not display correctly (text is same color as background).

I am also using a custom NSLayoutManager (to draw invisibles).

Unfortunately, there is an intermittent aspect to this. I use this subclass in several places and it works on my setup on the main editor, but not with some customers.

Then I found a different use of the same subclass that does not work for me. When it does not work, it is consistent for that user.

I have manually marked the textViews as using TextKit 1, with no change. I also tried the Clips Bounds to yes, again no change.

If I change the class to NSTextView, the text displays properly, but I lose existing functionality.

There appears to be some undocumented behavior change in Xcode 15 (or when linking against Sonoma SDK) that for subclasses of NSTextView (stored in XIB files). I know that there is a push to move toward TextKit 2, but it seems TextKit 1 support was possibly changed as well.

The text is there and I can edit it, double click, copy and paste it, it is just invisible, when compiled with Xcode 15 (also 15.1).

It has to be something very subtle that the subclassed TextView from one XIB will work, but from another XIB will not.

Does anyone have any insight into the potential change with TextKit 1 implementation?

Thanks.

Accepted Reply

Update: Issue fixed.

Initially I thought it was a clipsToBounds issue on a programmatically created ruler used to display line numbers. This wasn't showing up in XIB because the line numbers aren't always displayed. So setting the ruler's clipsToBounds seemed like the solution.

rulerView.clipsToBounds = YES; 

And it does fix the problem, but something felt off. I rewatched the "What's new in AppKit" from WWDC23 and there was an emphasis that we likely did not need to use clipsToBounds except in very specific cases. So I reviewed the ruler drawing code and found that it was actually using the dirtyRect parameter instead of its bounds when filling the background. Clearly, dirtyRect was much bigger now, but when clipsToBounds = YES, it essentially keeps the fill limited to the bounds, but it hid the root cause of the problem.

In the end, the better solution was to fix the drawing code to use its bounds instead of the dirtyRect, so it works regardless of whether clipsToBounds is true or false.

Replies

Update: Issue fixed.

Initially I thought it was a clipsToBounds issue on a programmatically created ruler used to display line numbers. This wasn't showing up in XIB because the line numbers aren't always displayed. So setting the ruler's clipsToBounds seemed like the solution.

rulerView.clipsToBounds = YES; 

And it does fix the problem, but something felt off. I rewatched the "What's new in AppKit" from WWDC23 and there was an emphasis that we likely did not need to use clipsToBounds except in very specific cases. So I reviewed the ruler drawing code and found that it was actually using the dirtyRect parameter instead of its bounds when filling the background. Clearly, dirtyRect was much bigger now, but when clipsToBounds = YES, it essentially keeps the fill limited to the bounds, but it hid the root cause of the problem.

In the end, the better solution was to fix the drawing code to use its bounds instead of the dirtyRect, so it works regardless of whether clipsToBounds is true or false.