NSTextField with tabs in text displays incorrectly in 10.12.2

Originator:rsfinn
Number:rdar://29758498 Date Originated:20-Dec-2016
Status:Closed Resolved:Fixed in 10.12.4
Product:macOS + SDK Product Version:10.12.2
Classification:UI Reproducible:Always
 
Summary:
An NSTextField contains text with tabs in order to display a data table. The text has an NSParagraphStyle with its tabStops property set to an array containing a number of right-aligned NSTextTabs. The text field was drawn as intended (with the text aligned to the tab stops) before upgrading to 10.12.2. After upgraded, the text was no longer aligned to the tab stops, and when using monospacedDigitsSystemFont there were cosmetic glitches displayed as well.  See the attached screen shots.

Steps to Reproduce:
Build and run the attached test project with Xcode 8 (any version) under macOS 10.12.2.  Use the popup button to select the font for the text field (system font; system font with monospaced digits; and user font).

Expected Results:
The window should display a data table with the numbers in right-aligned columns, no matter which font is selected.

Actual Results:
With the system font selected, the text in the table appears as though the tabs were spaces, without any alignment. If the font is changed to the monospaced digits variation, cosmetic graphic glitches appear where the tab characters are located (see the attached screenshots). Neither of these are desirable.

[Switching to the user font displays the text in aligned columns as intended.]

Version:
macOS 10.12.2 (16C67)

Notes:
This problem did not exist before 10.12.2 (including earlier OS releases; I tested back as far as 10.9.5).

Workarounds (see the attached "Additional Notes" file for more discussion):
1) Don't use the system font (use the user font instead, e.g.)
2) Use an NSTextView instead of an NSTextField
3) Ensure that wantsLayer is set on the window's content view

Configuration:
MacBookPro11,5 
16 GB RAM
512 GB SSD
macOS 10.12.2 (16C67)

-----

Additional note: When running the application in Xcode, at the point at which the erroneous text field display occurs, the system displays repeated copies of the following message in the console:
CoreText: *** Unmapped "\t" ".SFNSText 11.00 pt. P [] (0x10486a490) fobj=0x10486a490, spc=3.17"
The hexadecimal number (address?) can vary.  Typically there are ten copies of this message, with the address staying the same for four messages, then changing for the next four, etc.  (I have no insight as to why ten messages appear.)

Comments

Fixed in 10.12.4

The bug was (finally) fixed in macOS 10.12.4 and the workaround is no longer necessary (except for backward compatibility, of course).

Closed as duplicate; original also closed; bug still present in 10.12.3

On January 9, 2017, my bug report was closed as a duplicate of another bug (29493895).

On January 10 the original bug was also closed. Unfortunately I do not know why (e.g. was it fixed, was it marked "won't fix", or what).

The problem is still present in 10.12.3; the workaround (adding wantsLayer to the window's content view) continues to work.

Console messages

When running the application in Xcode, at the point at which the erroneous text field display occurs, the system displays repeated copies of the following message in the console:

CoreText: *** Unmapped "\t" ".SFNSText 11.00 pt. P [] (0x10486a490) fobj=0x10486a490, spc=3.17"

The hexadecimal number (address?) can vary. Typically there are ten copies of this message, with the address staying the same for four messages, then changing for the next four, etc. (I have no insight as to why ten messages appear.)

Screenshots on my blog

I wrote up a blog post describing this issue in more detail (including screenshots): http://russellfinn.com/2016/12/20/appkit-bug-in-10-12-2-nstextfield-with-tabs-in-text-displays-incorrectly/

Additional notes

Under time pressure for a release I implement the workaround of replacing the NSTextField with an NSTextView. I did this dynamically since it is not obvious how to create "bare" NSTextViews in Xcode's Interface Builder. Using an NSTextView I was able to get the data table to display as I had intended.

When writing up this bug I tried to create a simple test case that would illustrate the issue, but it did not appear on first try. When I copied the code and .xib file from my application into the test project, I was able to reproduce the issue. By examining the text of the .xib files, I discovered that the newly created .xib file has a content view with wantsLayer="YES", and this works properly; but the .xib file from my application (which was created before Xcode 8 was released) did not have a layer set on the content view. Setting a layer on the application's window's content view (in the View Effects tab of the Assistant Editor) was sufficient to fix the issue and make the table appear as intended.

I would urge Apple to test the case where wantsLayer is not set more thoroughly, and/or emphasize to the developer community that wantsLayer is intended to be the default case for content views going forward.


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!